2 * Namespace for comments
7 * Comment support for WCF
9 * @author Alexander Ebert
10 * @copyright 2001-2014 WoltLab GmbH
11 * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
13 WCF
.Comment
.Handler
= Class
.extend({
15 * input element to add a comment
21 * list of comment buttons per comment
24 _commentButtonList
: { },
27 * list of comment objects
33 * comment container object
45 * number of currently displayed comments
48 _displayedComments
: 0,
51 * button to load next comments
54 _loadNextComments
: null,
57 * buttons to load next responses per comment
60 _loadNextResponses
: { },
64 * @var WCF.Action.Proxy
69 * list of response objects
81 * data of the comment the active guest user is about to create
87 * guest dialog with username input field and recaptcha
93 * true if the guest has to solve a recaptcha challenge to save the comment
99 * Initializes the WCF.Comment.Handler class.
101 * @param string containerID
102 * @param string userAvatar
104 init: function(containerID
, userAvatar
) {
105 this._commentAdd
= null;
106 this._commentButtonList
= { };
107 this._comments
= { };
108 this._containerID
= containerID
;
109 this._displayedComments
= 0;
110 this._loadNextComments
= null;
111 this._loadNextResponses
= { };
112 this._responses
= { };
113 this._userAvatar
= userAvatar
;
115 this._container
= $('#' + $.wcfEscapeID(this._containerID
));
116 if (!this._container
.length
) {
117 console
.debug("[WCF.Comment.Handler] Unable to find container identified by '" + this._containerID
+ "'");
120 this._proxy
= new WCF
.Action
.Proxy({
121 failure
: $.proxy(this._failure
, this),
122 success
: $.proxy(this._success
, this)
125 this._initComments();
126 this._initResponses();
129 if (this._container
.data('canAdd')) {
130 this._initAddComment();
133 WCF
.DOMNodeInsertedHandler
.execute();
134 WCF
.DOMNodeInsertedHandler
.addCallback('WCF.Comment.Handler', $.proxy(this._domNodeInserted
, this));
138 * Shows a button to load next comments.
140 _handleLoadNextComments: function() {
141 if (this._displayedComments
< this._container
.data('comments')) {
142 if (this._loadNextComments
=== null) {
143 this._loadNextComments
= $('<li class="commentLoadNext"><button class="small">' + WCF
.Language
.get('wcf.comment.more') + '</button></li>').appendTo(this._container
);
144 this._loadNextComments
.children('button').click($.proxy(this._loadComments
, this));
147 this._loadNextComments
.children('button').enable();
149 else if (this._loadNextComments
!== null) {
150 this._loadNextComments
.hide();
155 * Shows a button to load next responses per comment.
157 * @param integer commentID
159 _handleLoadNextResponses: function(commentID
) {
160 var $comment
= this._comments
[commentID
];
161 $comment
.data('displayedResponses', $comment
.find('ul.commentResponseList > li').length
);
163 if ($comment
.data('displayedResponses') < $comment
.data('responses')) {
164 if (this._loadNextResponses
[commentID
] === undefined) {
165 var $difference
= $comment
.data('responses') - $comment
.data('displayedResponses');
166 this._loadNextResponses
[commentID
] = $('<li class="jsCommentLoadNextResponses"><a>' + WCF
.Language
.get('wcf.comment.response.more', { count
: $difference
}) + '</a></li>').appendTo(this._commentButtonList
[commentID
]);
167 this._loadNextResponses
[commentID
].children('a').data('commentID', commentID
).click($.proxy(this._loadResponses
, this));
168 this._commentButtonList
[commentID
].parent().show();
171 else if (this._loadNextResponses
[commentID
] !== undefined) {
172 var $showAddResponse
= this._loadNextResponses
[commentID
].next();
173 this._loadNextResponses
[commentID
].remove();
174 if ($showAddResponse
.length
) {
175 $showAddResponse
.trigger('click');
181 * Loads next comments.
183 _loadComments: function() {
184 this._loadNextComments
.children('button').disable();
186 this._proxy
.setOption('data', {
187 actionName
: 'loadComments',
188 className
: 'wcf\\data\\comment\\CommentAction',
191 objectID
: this._container
.data('objectID'),
192 objectTypeID
: this._container
.data('objectTypeID'),
193 lastCommentTime
: this._container
.data('lastCommentTime')
197 this._proxy
.sendRequest();
201 * Loads next responses for given comment.
203 * @param object event
205 _loadResponses: function(event
) {
206 this._loadResponsesExecute($(event
.currentTarget
).disable().data('commentID'), false);
211 * Executes loading of comments, optionally fetching all at once.
213 * @param integer commentID
214 * @param boolean loadAllResponses
216 _loadResponsesExecute: function(commentID
, loadAllResponses
) {
217 this._proxy
.setOption('data', {
218 actionName
: 'loadResponses',
219 className
: 'wcf\\data\\comment\\response\\CommentResponseAction',
222 commentID
: commentID
,
223 lastResponseTime
: this._comments
[commentID
].data('lastResponseTime'),
224 loadAllResponses
: (loadAllResponses
? 1 : 0)
228 this._proxy
.sendRequest();
232 * Handles DOMNodeInserted events.
234 _domNodeInserted: function() {
235 this._initComments();
236 this._initResponses();
240 * Initializes available comments.
242 _initComments: function() {
244 var $loadedComments
= false;
245 this._container
.find('.jsComment').each(function(index
, comment
) {
246 var $comment
= $(comment
).removeClass('jsComment');
247 var $commentID
= $comment
.data('commentID');
248 self
._comments
[$commentID
] = $comment
;
250 var $insertAfter
= $comment
.find('ul.commentResponseList');
251 if (!$insertAfter
.length
) $insertAfter
= $comment
.find('.commentContent');
253 $container
= $('<div class="commentOptionContainer" />').hide().insertAfter($insertAfter
);
254 self
._commentButtonList
[$commentID
] = $('<ul />').appendTo($container
);
256 self
._handleLoadNextResponses($commentID
);
257 self
._initComment($commentID
, $comment
);
258 self
._displayedComments
++;
260 $loadedComments
= true;
263 if ($loadedComments
) {
264 this._handleLoadNextComments();
269 * Initializes a specific comment.
271 * @param integer commentID
272 * @param jQuery comment
274 _initComment: function(commentID
, comment
) {
275 if (this._container
.data('canAdd')) {
276 this._initAddResponse(commentID
, comment
);
279 if (comment
.data('canEdit')) {
280 var $editButton
= $('<li><a class="jsTooltip" title="' + WCF
.Language
.get('wcf.global.button.edit') + '"><span class="icon icon16 icon-pencil" /> <span class="invisible">' + WCF
.Language
.get('wcf.global.button.edit') + '</span></a></li>');
281 $editButton
.data('commentID', commentID
).appendTo(comment
.find('ul.commentOptions:eq(0)')).click($.proxy(this._prepareEdit
, this));
284 if (comment
.data('canDelete')) {
285 var $deleteButton
= $('<li><a class="jsTooltip" title="' + WCF
.Language
.get('wcf.global.button.delete') + '"><span class="icon icon16 icon-remove" /> <span class="invisible">' + WCF
.Language
.get('wcf.global.button.delete') + '</span></a></li>');
286 $deleteButton
.data('commentID', commentID
).appendTo(comment
.find('ul.commentOptions:eq(0)')).click($.proxy(this._delete
, this));
291 * Initializes available responses.
293 _initResponses: function() {
295 this._container
.find('.jsCommentResponse').each(function(index
, response
) {
296 var $response
= $(response
).removeClass('jsCommentResponse');
297 var $responseID
= $response
.data('responseID');
298 self
._responses
[$responseID
] = $response
;
300 self
._initResponse($responseID
, $response
);
305 * Initializes a specific response.
307 * @param integer responseID
308 * @param jQuery response
310 _initResponse: function(responseID
, response
) {
311 if (response
.data('canEdit')) {
312 var $editButton
= $('<li><a class="jsTooltip" title="' + WCF
.Language
.get('wcf.global.button.edit') + '"><span class="icon icon16 icon-pencil" /> <span class="invisible">' + WCF
.Language
.get('wcf.global.button.edit') + '</span></a></li>');
315 $editButton
.data('responseID', responseID
).appendTo(response
.find('ul.commentOptions:eq(0)')).click(function(event
) { self
._prepareEdit(event
, true); });
318 if (response
.data('canDelete')) {
319 var $deleteButton
= $('<li><a class="jsTooltip" title="' + WCF
.Language
.get('wcf.global.button.delete') + '"><span class="icon icon16 icon-remove" /> <span class="invisible">' + WCF
.Language
.get('wcf.global.button.delete') + '</span></a></li>');
322 $deleteButton
.data('responseID', responseID
).appendTo(response
.find('ul.commentOptions:eq(0)')).click(function(event
) { self
._delete(event
, true); });
327 * Initializes the UI components to add a comment.
329 _initAddComment: function() {
331 this._commentAdd
= $('<li class="box32 jsCommentAdd"><span class="framed">' + this._userAvatar
+ '</span><div /></li>').prependTo(this._container
);
332 var $inputContainer
= this._commentAdd
.children('div');
333 var $input
= $('<input type="text" placeholder="' + WCF
.Language
.get('wcf.comment.add') + '" maxlength="65535" class="long" />').appendTo($inputContainer
);
334 $('<small>' + WCF
.Language
.get('wcf.comment.description') + '</small>').appendTo($inputContainer
);
336 $input
.keyup($.proxy(this._keyUp
, this));
340 * Initializes the UI elements to add a response.
342 * @param integer commentID
343 * @param jQuery comment
345 _initAddResponse: function(commentID
, comment
) {
346 var $placeholder
= null;
347 if (!comment
.data('responses') || this._loadNextResponses
[commentID
]) {
348 $placeholder
= $('<li class="jsCommentShowAddResponse"><a>' + WCF
.Language
.get('wcf.comment.button.response.add') + '</a></li>').data('commentID', commentID
).click($.proxy(this._showAddResponse
, this)).appendTo(this._commentButtonList
[commentID
]);
351 var $listItem
= $('<div class="box32 commentResponseAdd jsCommentResponseAdd"><span class="framed">' + this._userAvatar
+ '</span><div /></div>');
352 if ($placeholder
!== null) {
356 this._commentButtonList
[commentID
].parent().addClass('jsAddResponseActive');
358 $listItem
.appendTo(this._commentButtonList
[commentID
].parent().show());
360 var $inputContainer
= $listItem
.children('div');
361 var $input
= $('<input type="text" placeholder="' + WCF
.Language
.get('wcf.comment.response.add') + '" maxlength="65535" class="long" />').data('commentID', commentID
).appendTo($inputContainer
);
362 $('<small>' + WCF
.Language
.get('wcf.comment.description') + '</small>').appendTo($inputContainer
);
365 $input
.keyup(function(event
) { self
._keyUp(event
, true); });
367 comment
.data('responsePlaceholder', $placeholder
).data('responseInput', $listItem
);
371 * Prepares editing of a comment or response.
373 * @param object event
374 * @param boolean isResponse
376 _prepareEdit: function(event
, isResponse
) {
377 var $button
= $(event
.currentTarget
);
379 objectID
: this._container
.data('objectID'),
380 objectTypeID
: this._container
.data('objectTypeID')
383 if (isResponse
=== true) {
384 $data
.responseID
= $button
.data('responseID');
387 $data
.commentID
= $button
.data('commentID');
390 this._proxy
.setOption('data', {
391 actionName
: 'prepareEdit',
392 className
: 'wcf\\data\\comment\\CommentAction',
397 this._proxy
.sendRequest();
401 * Displays the UI elements to create a response.
403 * @param object event
405 _showAddResponse: function(event
) {
406 var $placeholder
= $(event
.currentTarget
);
407 var $commentID
= $placeholder
.data('commentID');
408 if ($placeholder
.prev().hasClass('jsCommentLoadNextResponses')) {
409 this._loadResponsesExecute($commentID
, true);
410 $placeholder
.parent().children('.button').disable();
413 $placeholder
.remove();
415 var $responseInput
= this._comments
[$commentID
].data('responseInput').show();
416 $responseInput
.find('input').focus();
418 $responseInput
.parents('.commentOptionContainer').addClass('jsAddResponseActive');
422 * Handles the keyup event for comments and responses.
424 * @param object event
425 * @param boolean isResponse
427 _keyUp: function(event
, isResponse
) {
428 // ignore every key except for [Enter] and [Esc]
429 if (event
.which
!== 13 && event
.which
!== 27) {
433 var $input
= $(event
.currentTarget
);
436 if (event
.which
=== 27) {
437 $input
.val('').trigger('blur', event
);
441 var $value
= $.trim($input
.val());
443 // ignore empty comments
448 var $actionName
= 'addComment';
451 objectID
: this._container
.data('objectID'),
452 objectTypeID
: this._container
.data('objectTypeID')
454 if (isResponse
=== true) {
455 $actionName
= 'addResponse';
456 $data
.commentID
= $input
.data('commentID');
459 if (!WCF
.User
.userID
) {
460 this._commentData
= $data
;
462 // check if guest dialog has already been loaded
463 if (this._guestDialog
=== null) {
464 this._proxy
.setOption('data', {
465 actionName
: 'getGuestDialog',
466 className
: 'wcf\\data\\comment\\CommentAction',
470 objectID
: this._container
.data('objectID'),
471 objectTypeID
: this._container
.data('objectTypeID')
475 this._proxy
.sendRequest();
478 // request a new recaptcha
479 if (this._useRecaptcha
) {
483 this._guestDialog
.find('input[type="submit"]').enable();
485 this._guestDialog
.wcfDialog('open');
489 this._proxy
.setOption('data', {
490 actionName
: $actionName
,
491 className
: 'wcf\\data\\comment\\CommentAction',
496 this._proxy
.sendRequest();
501 * Shows a confirmation message prior to comment or response deletion.
503 * @param object event
504 * @param boolean isResponse
506 _delete: function(event
, isResponse
) {
507 WCF
.System
.Confirmation
.show(WCF
.Language
.get('wcf.comment.delete.confirmMessage'), $.proxy(function(action
) {
508 if (action
=== 'confirm') {
510 objectID
: this._container
.data('objectID'),
511 objectTypeID
: this._container
.data('objectTypeID')
513 if (isResponse
!== true) {
514 $data
.commentID
= $(event
.currentTarget
).data('commentID');
517 $data
.responseID
= $(event
.currentTarget
).data('responseID');
520 this._proxy
.setOption('data', {
521 actionName
: 'remove',
522 className
: 'wcf\\data\\comment\\CommentAction',
527 this._proxy
.sendRequest();
533 * Handles a failed AJAX request.
536 * @param object jqXHR
537 * @param string textStatus
538 * @param string errorThrown
541 _failure: function(data
, jqXHR
, textStatus
, errorThrown
) {
542 if (!WCF
.User
.userID
&& this._guestDialog
) {
543 // enable submit button again
544 this._guestDialog
.find('input[type="submit"]').enable();
551 * Handles successful AJAX requests.
554 * @param string textStatus
555 * @param jQuery jqXHR
557 _success: function(data
, textStatus
, jqXHR
) {
558 switch (data
.actionName
) {
560 if (data
.returnValues
.errors
) {
561 this._handleGuestDialogErrors(data
.returnValues
.errors
);
564 this._commentAdd
.find('input').val('').blur();
565 $(data
.returnValues
.template
).insertAfter(this._commentAdd
).wcfFadeIn();
567 if (!WCF
.User
.userID
) {
568 this._guestDialog
.wcfDialog('close');
574 if (data
.returnValues
.errors
) {
575 this._handleGuestDialogErrors(data
.returnValues
.errors
);
578 var $comment
= this._comments
[data
.returnValues
.commentID
];
579 $comment
.find('.jsCommentResponseAdd input').val('').blur();
581 var $responseList
= $comment
.find('ul.commentResponseList');
582 if (!$responseList
.length
) $responseList
= $('<ul class="commentResponseList" />').insertBefore($comment
.find('.commentOptionContainer'));
583 $(data
.returnValues
.template
).appendTo($responseList
).wcfFadeIn();
586 if (!WCF
.User
.userID
) {
587 this._guestDialog
.wcfDialog('close');
596 this._insertComments(data
);
599 case 'loadResponses':
600 this._insertResponses(data
);
611 case 'getGuestDialog':
612 this._createGuestDialog(data
);
616 WCF
.DOMNodeInsertedHandler
.execute();
620 * Inserts previously loaded comments.
624 _insertComments: function(data
) {
626 $(data
.returnValues
.template
).insertBefore(this._loadNextComments
);
628 // update time of last comment
629 this._container
.data('lastCommentTime', data
.returnValues
.lastCommentTime
);
633 * Inserts previously loaded responses.
637 _insertResponses: function(data
) {
638 var $comment
= this._comments
[data
.returnValues
.commentID
];
641 $(data
.returnValues
.template
).appendTo($comment
.find('ul.commentResponseList'));
643 // update time of last response
644 $comment
.data('lastResponseTime', data
.returnValues
.lastResponseTime
);
646 // update button state to load next responses
647 this._handleLoadNextResponses(data
.returnValues
.commentID
);
651 * Removes a comment or response from list.
655 _remove: function(data
) {
656 if (data
.returnValues
.commentID
) {
657 this._comments
[data
.returnValues
.commentID
].remove();
658 delete this._comments
[data
.returnValues
.commentID
];
661 this._responses
[data
.returnValues
.responseID
].remove();
662 delete this._responses
[data
.returnValues
.responseID
];
667 * Prepares editing of a comment or response.
671 _edit: function(data
) {
672 if (data
.returnValues
.commentID
) {
673 var $content
= this._comments
[data
.returnValues
.commentID
].find('.commentContent:eq(0) .userMessage:eq(0)');
676 var $content
= this._responses
[data
.returnValues
.responseID
].find('.commentContent:eq(0) .userMessage:eq(0)');
679 // replace content with input field
680 $content
.html($.proxy(function(index
, oldHTML
) {
681 var $input
= $('<input type="text" class="long" maxlength="65535" /><small>' + WCF
.Language
.get('wcf.comment.description') + '</small>').val(data
.returnValues
.message
);
682 $input
.data('__html', oldHTML
).keyup($.proxy(this._saveEdit
, this));
684 if (data
.returnValues
.commentID
) {
685 $input
.data('commentID', data
.returnValues
.commentID
);
688 $input
.data('responseID', data
.returnValues
.responseID
);
693 $content
.children('input').focus();
696 $content
.parent().find('.containerHeadline:eq(0)').hide();
697 $content
.parent().find('.buttonGroupNavigation:eq(0)').hide();
701 * Updates a comment or response.
705 _update: function(data
) {
706 if (data
.returnValues
.commentID
) {
707 var $input
= this._comments
[data
.returnValues
.commentID
].find('.commentContent:eq(0) .userMessage:eq(0) > input');
710 var $input
= this._responses
[data
.returnValues
.responseID
].find('.commentContent:eq(0) .userMessage:eq(0) > input');
713 $input
.data('__html', data
.returnValues
.message
);
715 this._cancelEdit($input
);
719 * Creates the guest dialog based on the given return data from the AJAX
724 _createGuestDialog: function(data
) {
725 this._guestDialog
= $('<div id="commentAddGuestDialog" />').append(data
.returnValues
.template
).hide().appendTo(document
.body
);
727 // bind submit event listeners
728 this._guestDialog
.find('input[type="submit"]').click($.proxy(this._submit
, this));
730 this._guestDialog
.find('input[type="text"]').keydown($.proxy(this._keyDown
, this));
732 // check if recaptcha is used
733 this._useRecaptcha
= this._guestDialog
.find('dl.reCaptcha').length
> 0;
735 this._guestDialog
.wcfDialog({
736 'title': WCF
.Language
.get('wcf.comment.guestDialog.title')
741 * Handles clicking enter in the input fields of the guest dialog by
746 _keyDown: function(event
) {
747 if (event
.which
=== $.ui
.keyCode
.ENTER
) {
753 * Handles errors during creation of a comment or response due to the input
754 * in the guest dialog.
756 * @param object errors
758 _handleGuestDialogErrors: function(errors
) {
759 if (errors
.username
) {
760 var $usernameInput
= this._guestDialog
.find('input[name="username"]');
761 var $errorMessage
= $usernameInput
.next('.innerError');
762 if (!$errorMessage
.length
) {
763 $errorMessage
= $('<small class="innerError" />').text(errors
.username
).insertAfter($usernameInput
);
766 $errorMessage
.text(errors
.username
).show();
770 if (errors
.recaptcha
) {
773 var $recaptchaInput
= this._guestDialog
.find('input[name="recaptcha_response_field"]');
774 var $errorMessage
= $recaptchaInput
.next('.innerError');
775 if (!$errorMessage
.length
) {
776 $errorMessage
= $('<small class="innerError" />').text(errors
.recaptcha
).insertAfter($recaptchaInput
);
779 $errorMessage
.text(errors
.recaptcha
).show();
783 this._guestDialog
.find('input[type="submit"]').enable();
787 * Handles submitting the guest dialog.
791 _submit: function(event
) {
794 this._guestDialog
.find('input[type="submit"]').enable();
797 var $usernameInput
= this._guestDialog
.find('input[name="username"]');
798 var $username
= $usernameInput
.val();
799 var $usernameErrorMessage
= $usernameInput
.next('.innerError');
802 if (!$usernameErrorMessage
.length
) {
803 $usernameErrorMessage
= $('<small class="innerError" />').text(WCF
.Language
.get('wcf.global.form.error.empty')).insertAfter($usernameInput
);
806 $usernameErrorMessage
.text(WCF
.Language
.get('wcf.global.form.error.empty')).show();
810 // validate recaptcha
811 if (this._useRecaptcha
) {
812 var $recaptchaInput
= this._guestDialog
.find('input[name="recaptcha_response_field"]');
813 var $recaptchaResponse
= $recaptchaInput
.val();
814 var $recaptchaErrorMessage
= $recaptchaInput
.next('.innerError');
815 if (!$recaptchaResponse
) {
817 if (!$recaptchaErrorMessage
.length
) {
818 $recaptchaErrorMessage
= $('<small class="innerError" />').text(WCF
.Language
.get('wcf.global.form.error.empty')).insertAfter($recaptchaInput
);
821 $recaptchaErrorMessage
.text(WCF
.Language
.get('wcf.global.form.error.empty')).show();
827 if ($usernameErrorMessage
.length
) {
828 $usernameErrorMessage
.hide();
831 if (this._useRecaptcha
&& $recaptchaErrorMessage
.length
) {
832 $recaptchaErrorMessage
.hide();
835 var $data
= this._commentData
;
836 $data
.username
= $username
;
842 if (this._useRecaptcha
) {
843 $parameters
.recaptchaChallenge
= Recaptcha
.get_challenge();
844 $parameters
.recaptchaResponse
= Recaptcha
.get_response();
847 this._proxy
.setOption('data', {
848 actionName
: this._commentData
.commentID
? 'addResponse' : 'addComment',
849 className
: 'wcf\\data\\comment\\CommentAction',
850 parameters
: $parameters
852 this._proxy
.sendRequest();
854 this._guestDialog
.find('input[type="submit"]').disable();
859 * Saves editing of a comment or response.
861 * @param object event
863 _saveEdit: function(event
) {
864 var $input
= $(event
.currentTarget
);
867 if (event
.which
=== 27) {
868 this._cancelEdit($input
);
871 else if (event
.which
!== 13) {
872 // ignore everything except for [Enter]
876 var $message
= $.trim($input
.val());
878 // ignore empty message
879 if ($message
=== '') {
885 objectID
: this._container
.data('objectID'),
886 objectTypeID
: this._container
.data('objectTypeID')
888 if ($input
.data('commentID')) {
889 $data
.commentID
= $input
.data('commentID');
892 $data
.responseID
= $input
.data('responseID');
895 this._proxy
.setOption('data', {
897 className
: 'wcf\\data\\comment\\CommentAction',
902 this._proxy
.sendRequest()
906 * Cancels editing of a comment or response.
908 * @param jQuery input
910 _cancelEdit: function(input
) {
912 input
.parent().prev('.containerHeadline:eq(0)').show();
913 input
.parent().next('.buttonGroupNavigation:eq(0)').show();
916 input
.parent().html(input
.data('__html'));
921 * Like support for comments
925 WCF
.Comment
.Like
= WCF
.Like
.extend({
927 * @see WCF.Like._getContainers()
929 _getContainers: function() {
930 return $('.commentList > li.comment');
934 * @see WCF.Like._getObjectID()
936 _getObjectID: function(containerID
) {
937 return this._containers
[containerID
].data('commentID');
941 * @see WCF.Like._buildWidget()
943 _buildWidget: function(containerID
, likeButton
, dislikeButton
, badge
, summary
) {
944 this._containers
[containerID
].find('.containerHeadline:eq(0) > h3').append(badge
);
947 likeButton
.appendTo(this._containers
[containerID
].find('.commentOptions:eq(0)'));
948 dislikeButton
.appendTo(this._containers
[containerID
].find('.commentOptions:eq(0)'));
953 * @see WCF.Like._getWidgetContainer()
955 _getWidgetContainer: function(containerID
) {},
958 * @see WCF.Like._addWidget()
960 _addWidget: function(containerID
, widget
) {}
964 * Namespace for comment responses
966 WCF
.Comment
.Response
= { };
969 * Like support for comments responses.
973 WCF
.Comment
.Response
.Like
= WCF
.Like
.extend({
975 * @see WCF.Like._addWidget()
977 _addWidget: function(containerID
, widget
) { },
980 * @see WCF.Like._buildWidget()
982 _buildWidget: function(containerID
, likeButton
, dislikeButton
, badge
, summary
) {
983 this._containers
[containerID
].find('.containerHeadline:eq(0) > h3').append(badge
);
986 likeButton
.appendTo(this._containers
[containerID
].find('.commentOptions:eq(0)'));
987 dislikeButton
.appendTo(this._containers
[containerID
].find('.commentOptions:eq(0)'));
992 * @see WCF.Like._getContainers()
994 _getContainers: function() {
995 return $('.commentResponseList > li.commentResponse');
999 * @see WCF.Like._getObjectID()
1001 _getObjectID: function(containerID
) {
1002 return this._containers
[containerID
].data('responseID');
1006 * @see WCF.Like._getWidgetContainer()
1008 _getWidgetContainer: function(containerID
) { }