diff --git a/code/Commenting.php b/code/Commenting.php index 1339754..95e2928 100644 --- a/code/Commenting.php +++ b/code/Commenting.php @@ -33,7 +33,8 @@ class Commenting { 'comment_permalink_prefix' => "comment-", // id prefix for each comment. If needed make this different 'require_moderation' => false, 'html_allowed' => false, // allow for sanitized HTML in comments - 'html_allowed_elements' => array('p', 'br', 'a', 'img', 'i', 'b') + 'html_allowed_elements' => array('p', 'br', 'a', 'img', 'i', 'b'), + 'use_preview' => false, // preview formatted comment (when allowing HTML) ); /** diff --git a/code/controllers/CommentingController.php b/code/controllers/CommentingController.php index 9598576..79b4bf4 100644 --- a/code/controllers/CommentingController.php +++ b/code/controllers/CommentingController.php @@ -13,7 +13,8 @@ class CommentingController extends Controller { 'approve', 'rss', 'CommentsForm', - 'doPostComment' + 'doPostComment', + 'doPreviewComment' ); private $baseClass = ""; @@ -239,7 +240,7 @@ class CommentingController extends Controller { * @return Form */ public function CommentsForm() { - + $usePreview = Commenting::get_config_value($this->getBaseClass(), 'use_preview'); $member = Member::currentUser(); $fields = new FieldList( TextField::create("Name", _t('CommentInterface.YOURNAME', 'Your name')) @@ -263,10 +264,28 @@ class CommentingController extends Controller { HiddenField::create("BaseClass") ); + // Preview formatted comment. Makes most sense when shortcodes or + // limited HTML is allowed. Populated by JS/Ajax. + if($usePreview) { + $fields->insertAfter( + ReadonlyField::create('PreviewComment', _t('CommentInterface.PREVIEWLABEL', 'Preview')) + ->setAttribute('style', 'display: none'), // enable through JS + 'Comment' + ); + } + + // save actions $actions = new FieldList( new FormAction("doPostComment", _t('CommentInterface.POST', 'Post')) ); + if($usePreview) { + $actions->push( + FormAction::create('doPreviewComment', _t('CommentInterface.PREVIEW', 'Preview')) + ->addExtraClass('action-minor') + ->setAttribute('style', 'display: none') // enable through JS + ); + } // required fields for server side $required = new RequiredFields(array( @@ -340,6 +359,8 @@ class CommentingController extends Controller { */ public function doPostComment($data, $form) { $class = (isset($data['BaseClass'])) ? $data['BaseClass'] : $this->getBaseClass(); + $usePreview = Commenting::get_config_value($class, 'use_preview'); + $isPreview = ($usePreview && isset($data['preview']) && $data['preview']); // if no class then we cannot work out what controller or model they // are on so throw an error @@ -378,7 +399,13 @@ class CommentingController extends Controller { $form->saveInto($comment); $comment->Moderated = ($moderated) ? false : true; - $comment->write(); + + // Save into DB, or call pre-save hooks to give accurate preview + if($isPreview) { + $comment->onBeforeWrite(); + } else { + $comment->write(); + } // extend hook to allow extensions. Also see onBeforePostComment $this->extend('onAfterPostComment', $comment); @@ -401,4 +428,9 @@ class CommentingController extends Controller { return ($url) ? $this->redirect($url .'#'. $hash) : $this->redirectBack(); } + + public function doPreviewComment($data, $form) { + $data['IsPreview'] = 1; + return $this->doPostComment($data, $form); + } } diff --git a/docs/en/Configuration.md b/docs/en/Configuration.md index 2e68462..5a56210 100644 --- a/docs/en/Configuration.md +++ b/docs/en/Configuration.md @@ -17,7 +17,8 @@ The module provides a number of built in configuration settings below are the de 'comment_permalink_prefix' => "comment-", 'require_moderation' => false, 'html_allowed' => false, // allow for sanitized HTML in comments - 'html_allowed_elements' => array('p', 'br', 'a', 'img', 'i', 'b') + 'html_allowed_elements' => array('p', 'br', 'a', 'img', 'i', 'b'), + 'use_preview' => false, // preview formatted comment (when allowing HTML) ); If you want to customize any of the configuration options after you have added the extension (or diff --git a/javascript/CommentsInterface.js b/javascript/CommentsInterface.js index 3336a4d..a3f0f49 100755 --- a/javascript/CommentsInterface.js +++ b/javascript/CommentsInterface.js @@ -9,8 +9,14 @@ commentsList = $('.comments-list', commentsHolder), pagination = $('.comments-pagination'), noCommentsYet = $('.no-comments-yet', commentsHolder), - form = $('form', container); + form = $('form', container), + previewEl = form.find('#PreviewComment'); + /** + * Init + */ + previewEl.hide(); + $(':submit[name=action_doPreviewComment]').show(); /** * Validate @@ -70,7 +76,6 @@ * this inclues the spam and approve links */ form.submit(function (e) { - // trigger validation if(!form.validate().valid()){ return false; @@ -103,6 +108,36 @@ return false; }); + /** + * Preview comment by fetching it from the server via ajax. + */ + $(':submit[name=action_doPreviewComment]', form).click(function(e) { + e.preventDefault(); + + if(!form.validate().valid()) return false; + + previewEl.show().addClass('loading').find('.middleColumn').html(' '); + form.ajaxSubmit({ + success: function(response) { + var responseEl = $(response); + if(responseEl.is('form')) { + // Validation failed, renders form instead of single comment + form.replaceWith(responseEl); + } else { + // Default behaviour + previewEl.removeClass('loading').find('.middleColumn').html(responseEl); + } + }, + data: {'action_doPreviewComment': 1} + }); + }); + + /** + * Hide outdated preview on form changes + */ + $(':input', form).on('change keydown', function() { + previewEl.hide(); + }); /** * Clicking one of the metalinks performs the operation via ajax