From ff31c296b467ca5b93195ec4ebfae60cf4dcca57 Mon Sep 17 00:00:00 2001 From: Gordon Anderson Date: Fri, 12 Feb 2016 20:24:56 +0700 Subject: [PATCH] FIX: Added reply to link for non JS to avoid multiple forms. If using AJAX a hidden form is used. Fallback for JavaScript turned off in browsers --- code/controllers/CommentingController.php | 2 +- code/extensions/CommentsExtension.php | 16 ++++ code/model/Comment.php | 13 ++- javascript/CommentsInterface.js | 99 +++++++++++++------- javascript/lang/en.js | 2 + lang/en.yml | 2 + templates/CommentReplies.ss | 6 +- templates/CommentsInterface.ss | 4 +- templates/CommentsInterface_singlecomment.ss | 4 +- 9 files changed, 109 insertions(+), 39 deletions(-) diff --git a/code/controllers/CommentingController.php b/code/controllers/CommentingController.php index 8e17809..bab865a 100644 --- a/code/controllers/CommentingController.php +++ b/code/controllers/CommentingController.php @@ -629,7 +629,7 @@ class CommentingController extends Controller } elseif (!$comment->Moderated) { // Display the "awaiting moderation" text $holder = $this->getOption('comments_holder_id'); - $hash = "{$holder}_PostCommentForm_error"; + $hash = "moderated"; } else { // Link to the moderated, non-spam comment $hash = $comment->Permalink(); diff --git a/code/extensions/CommentsExtension.php b/code/extensions/CommentsExtension.php index 88ad47b..ce23807 100644 --- a/code/extensions/CommentsExtension.php +++ b/code/extensions/CommentsExtension.php @@ -480,6 +480,22 @@ class CommentsExtension extends DataExtension ->renderWith('CommentsInterface'); } + /* + JavaScript form reply requires an empty form, when the reply button is + clicked the correct values are inserted, the form moved, and then shown + */ + public function getReplyFormForJavaScript() { + // Build reply controller + $controller = CommentingController::create(); + $controller->setOwnerRecord($this->owner); + $controller->setBaseClass($this->owner->ClassName); + $controller->setOwnerController(Controller::curr()); + $comment = new Comment(); + $comment->ID='JSOnly'; + $comment->ParentID = $this->owner->ID; + return $controller->ReplyForm($comment); + } + /** * Returns whether this extension instance is attached to a {@link SiteTree} object * diff --git a/code/model/Comment.php b/code/model/Comment.php index 60491ed..f947fb4 100755 --- a/code/model/Comment.php +++ b/code/model/Comment.php @@ -46,7 +46,7 @@ class Comment extends DataObject ); private static $has_many = array( - "ChildComments" => "Comment" + "ChildComments" => "Comment" ); private static $default_sort = '"Created" DESC'; @@ -734,6 +734,17 @@ class Comment extends DataObject return $list; } + /** + * Ascertains whether or not to show the reply form + */ + public function ShowReplyToForm() { + $controller = Controller::curr(); + $request = $controller->getRequest(); + $replyTo = $request->getVar('replyTo'); + $result = $replyTo == $this->ID; + return $result; + } + /** * Returns the list of replies, with spam and unmoderated items excluded, for use in the frontend * diff --git a/javascript/CommentsInterface.js b/javascript/CommentsInterface.js index 255b517..8a9abc8 100755 --- a/javascript/CommentsInterface.js +++ b/javascript/CommentsInterface.js @@ -57,44 +57,81 @@ } }); - /** - * Comment reply form - */ - $( ".comment-replies-container .comment-reply-form-holder" ).entwine({ - onmatch: function() { - // If and only if this is not the currently selected form, hide it on page load - var selectedHash = window.document.location.hash.substr(1), - form = $(this).children('.reply-form'); - if( !selectedHash || selectedHash !== form.prop( 'id' ) ) { - this.hide(); - } - this._super(); - }, - onunmatch: function() { - this._super(); - } - }); - /** * Toggle on/off reply form */ $( ".comment-reply-link" ).entwine({ onclick: function( e ) { - var allForms = $( ".comment-reply-form-holder" ), - formID = $( this ).prop('href').replace(/^[^#]*#/, '#'), - form = $(formID).closest('.comment-reply-form-holder'); + // Prevent focus + e.preventDefault(); - // Prevent focus - e.preventDefault(); - if(form.is(':visible')) { - allForms.slideUp(); - } else { - allForms.not(form).slideUp(); - form.slideDown(); - } + var jqTarget = $(e.target); + var commentID = jqTarget.attr('data-comment-id'); + container = $('#replyFormJS'); + var state = jqTarget.attr('data-state'); + + // Show possibly hidden reply form, alter state so that it works + // in context of relevant comment + if (state != 'replying') { + cancelTheCancels(); + toggleButtonText(jqTarget); + + // hide the form if it's visible + if(container.is(':visible')) { + container.toggle(); + } + + var jqComment = $('#reply-form-container-' + commentID); + var form = container.find('form'); + action = form.attr('action'); + form.attr('action', '/CommentingController/reply/' + commentID); + var inputParemtCommentID = container.find("input[name='ParentCommentID']"); + var inputComment = container.find("input[name='Comment']"); + inputParemtCommentID.attr('value', commentID); + inputComment.attr('value', ''); + container.detach().appendTo(jqComment); + + var allForms = $( ".comment-reply-form-holder" ), + formID = $( this ).prop('href').replace(/^[^#]*#/, '#'), + form = $(formID).closest('.comment-reply-form-holder'); + + // Show the form + container.toggle(); + + $('html, body').animate({ + scrollTop: container.offset().top - 30 + }, 200); + + } else { + // Cancel reply, hide form, change button text + toggleButtonText(jqTarget); + container.slideUp(); + } } }); + /** + * Revert buttons in a state of replying to that of cancelled, changing + * text back to 'Reply to ' + */ + function toggleButtonText(node) { + var state = node.attr('data-state'); + if (state != 'replying') { + node.html(ss.i18n._t('CommentsInterface_singlecomment_ss.CANCEL_REPLY')); + node.attr('data-state', 'replying'); + } else { + node.html(ss.i18n._t('CommentsInterface_singlecomment_ss.REPLY_TO')); + node.attr('data-state', 'cancelled'); + } + } + + function cancelTheCancels() { + var toFix = $("a[data-state='replying']"); + toFix.each(function(index) { + var jqTarget = $(this); + toggleButtonText(jqTarget); + }); + } /** * Preview comment by fetching it from the server via ajax. @@ -166,7 +203,7 @@ } else if(link.hasClass('delete')) { comment.fadeOut(1000, function() { - comment.remove(); + comment.remove(); if(commentsList.children().length === 0) { noCommentsYet.show(); @@ -212,5 +249,3 @@ });*/ }); })(jQuery); - - diff --git a/javascript/lang/en.js b/javascript/lang/en.js index 00d6876..917fed0 100644 --- a/javascript/lang/en.js +++ b/javascript/lang/en.js @@ -6,5 +6,7 @@ if (typeof(ss) == 'undefined' || typeof(ss.i18n) == 'undefined') { ss.i18n.addDictionary('en', { "CommentsInterface_singlecomment_ss.DELETE_CONFIRMATION": "Are you sure?", "CommentsInterface_singlecomment_ss.AJAX_ERROR": "An error occurred whilst updating the comment", + "CommentsInterface_singlecomment_ss.REPLY_TO" : "Reply to", + "CommentsInterface_singlecomment_ss.CANCEL_REPLY" : "Cancel Reply", }); } diff --git a/lang/en.yml b/lang/en.yml index f29a543..8854ad0 100644 --- a/lang/en.yml +++ b/lang/en.yml @@ -61,6 +61,8 @@ en: ISSPAM: 'spam it' PBY: 'Posted by' REMCOM: 'reject it' + REPLY_TO: 'Reply to' + CANCEL_REPLY: 'Cancel Reply' CommentsInterface_ss: AWAITINGMODERATION: 'Your comment has been submitted and is now awaiting moderation.' COMMENTLOGINERROR: 'You cannot post comments until you have logged in' diff --git a/templates/CommentReplies.ss b/templates/CommentReplies.ss index 0b8d9a4..410cb50 100644 --- a/templates/CommentReplies.ss +++ b/templates/CommentReplies.ss @@ -1,10 +1,10 @@ <% if $RepliesEnabled %>
-
- $ReplyForm + <%-- non ajax, only show if replyTo is set --%> + <% if $ShowReplyToForm %>$ReplyForm<% end_if %>
- +
<% if $Replies %>
    diff --git a/templates/CommentsInterface.ss b/templates/CommentsInterface.ss index 2a4b5af..2851557 100755 --- a/templates/CommentsInterface.ss +++ b/templates/CommentsInterface.ss @@ -25,7 +25,7 @@ <% if $PagedComments %>
      <% loop $PagedComments %> -
    • +
    • <% include CommentsInterface_singlecomment %>
    • <% end_loop %> @@ -51,3 +51,5 @@

<% end_if %> +<%-- include a hidden form for JS use when replying --%> + diff --git a/templates/CommentsInterface_singlecomment.ss b/templates/CommentsInterface_singlecomment.ss index 7182bca..f306b33 100755 --- a/templates/CommentsInterface_singlecomment.ss +++ b/templates/CommentsInterface_singlecomment.ss @@ -33,10 +33,12 @@ <% end_if %>
<% if $RepliesEnabled %> - Reply to $AuthorName.XML + <% _t('CommentsInterface_singlecomment_ss.REPLY_TO','Reply to') %> $AuthorName.XML <% end_if %> <% end_if %> +
+ <% include CommentReplies %> <% end_if %>