Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

enhancement showcase (ajax, gravatar, nested, delete) #65

Open
wants to merge 17 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
117 changes: 117 additions & 0 deletions assets/comments.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
/*
===============================================================================================================================
Comments Plugin Styles
===============================================================================================================================
*/

.comment {
margin-top: 15px;
border-top: gray solid 2px;
}
.comment:first-child {
margin-top: 0px;
}
.comment,
.comment-body {
zoom: 1;
overflow: hidden;
}
.comment-body {
width: 10000px;
}
.comment-object {
display: block;
}
.comment-right,
.comment > .pull-right {
padding-left: 10px;
}
.comment-left,
.comment > .pull-left {
padding-right: 10px;
}
.comment-left,
.comment-right,
.comment-body {
display: table-cell;
vertical-align: top;
}
.comment-middle {
vertical-align: middle;
}
.comment-bottom {
vertical-align: bottom;
}
.comment-heading {
margin-top: 0px;
margin-bottom: 5px;
border-bottom: gray dashed 1px;
}
.comment-title, .comment-title h4 {
padding: 0px;
margin: 0px;
}
.comment-meta {
display: inline;
font-size: small;
}
.comment-reply {
display: inline;
float: right;
}
.comment-text {
clear: both;
}
.comment-list {
padding-left: 0px;
list-style: none;
}
.comment-flag-new {
background-color: lightcyan;
}
.comment-level-1 { margin-left: 20px; padding-left: 0px; border-left: gray solid 0px; }
.comment-level-2 { margin-left: 40px; padding-left: 0px; border-left: gray solid 0px; }
.comment-level-3 { margin-left: 60px; padding-left: 0px; border-left: gray solid 0px; }
.comment-level-4 { margin-left: 80px; padding-left: 0px; border-left: gray solid 0px; }
.comment-level-5 { margin-left: 100px; padding-left: 0px; border-left: gray solid 0px; }
.row.comments { position: relative; }
.comment-level-1::before {
content: "\f105";
font-family: FontAwesome;
position: absolute;
left: 0px;
font-size: 3rem;
color: lightgray;
}
.comment-level-2::before {
content: "\f105\f105";
font-family: FontAwesome;
position: absolute;
left: 0px;
font-size: 3rem;
color: lightgray;
}
.comment-level-3::before {
content: "\f105\f105\f105";
font-family: FontAwesome;
position: absolute;
left: 0px;
font-size: 3rem;
color: lightgray;
}
.comment-level-4::before {
content: "\f105\f105\f105\f105";
font-family: FontAwesome;
position: absolute;
left: 0px;
font-size: 3rem;
color: lightgray;
}
.comment-level-5::before {
content: "\f105\f105\f105\f105\f105";
font-family: FontAwesome;
position: absolute;
left: 0px;
font-size: 3rem;
color: lightgray;
}
179 changes: 179 additions & 0 deletions assets/comments.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,179 @@
function escapeRegExp(str) {
return str.replace(/([.*+?^=!:${}()|\[\]\/\\])/g, "\\$1");
}
jQuery(document).ready(function () {
var commentForm = $('#comments-form'); //$(document).find('.comments-form').first();
var commentSection = $('#comments-section'); //$(document).find('.comments').first();
var commentAlert = $('#comments-alert'); //$(document).find('.alert').first();

//hide form, show link
commentForm.hide();
$(document).find('.comment-add-new').show();

//show comment form above comments section (new comment thread)
$('body').on('click', '.comment-add-new', function (e) {
e.preventDefault();
if ($(this).prev().filter('#comments-form').length > 0) {
//form is already in the right place.
//just make sure it is visible.
commentForm.show();
return;
}
commentForm.hide(); //hide it to make sure that it is not shown after move to make "show" transition work.
$(this).before(commentForm);
commentForm.show('slow');
commentAlert.empty().slideUp();
});

//show comment form below selected comment (reply to existing comment)
$('body').on('click', '.comment-add-reply', function (e) {
e.preventDefault();
var comment = $(this).closest('.comment');
if (comment.find('#comments-form').length > 0) {
//form is already in the right place.
//just make sure it is visible.
commentForm.show();
return;
}
commentForm.hide();
comment.find('.comment-body').last().append(commentForm);
commentForm.show('slow');
commentAlert.empty().slideUp();
});

//delete comment (authorized user only)
$('body').on('click', '.comment-delete', function (e) {
e.preventDefault();
var comment = $(this).closest('.comment');
var id = parseInt(comment.attr('data-id'), 10);
var level = parseInt(comment.attr('data-level'), 10);
var nonce = commentForm.find("input[name='form-nonce']").val();
if (comment.next().filter(".comment[data-level='" + (level + 1) + "']").length > 0) {
alert('Deletion not allowed. There are replies to this comment. Please delete them first.');
return;
}
var url = commentForm.attr( "action" );
var posting = $.post(url, { action: 'delete', id: id, nonce: nonce}, null, 'json');
// Register events to ajax call
posting.done(function (response) {

//make sure that commentForm is definitely not within the deleted DOM part.
//hide
//temporary move it outside the comment selected for deletion. (this definitely exists, not taking any chances here)
//finally move back to start of commentSection. (preferred target)
//Hint: Don't forget commentAlert as it is not inside the form.
commentAlert.empty().hide();
commentForm.hide();
comment.before(commentForm);
comment.before(commentAlert);
commentSection.prepend(commentAlert);
commentSection.prepend(commentForm);
//remove the comment and all content from DOM.
//detach would be a soft delete but as there is no reason to reuse the deleted comment, means should not be provided.
comment.remove();
});
posting.fail(function (status, error, title) {
//alert('error');
//console.log("Response Data (fail)", JSON.parse(JSON.stringify(status)));
commentForm.after(commentAlert);
commentAlert.show();
commentAlert.empty().append("<p>Error: </p>");
commentAlert.append("<p>" + JSON.stringify(status) + "</p>");
commentAlert.append("<p>" + JSON.stringify(error) + "</p>");
commentAlert.append("<p>" + JSON.stringify(title) + "</p>");
});
posting.always(function () {
//alert("finished, be it successful or not");
});
});

// Attach a submit handler to the form
$(commentForm).on('submit', function (event) {
event.preventDefault();
// Get form data:
var data = $(this).serialize();
//console.log("Form Data (submit)", JSON.parse(JSON.stringify(data)));
var url = $(this).attr( "action" );
//var url = '/nested-comments';
var parentId = 0;
var ownLevel = 0;
if ($(this).parents('.comment').length > 0) {
parentId = $(this).closest('.comment').attr('data-id');
ownLevel = parseInt($(this).closest('.comment').attr('data-level'), 10) + 1;
}

// Send the data using post
//var posting = $.post(url, { parentId: parentId, data: data }, null, 'json');
var posting = $.post(url, data + '&parentID=' + parentId, null, 'json');

// Register events to ajax call
posting.done(function (response) {
//alert('success');
//console.log("Response Data (done)", JSON.parse(JSON.stringify(response)));
//response = JSON.parse(response); //not needed, post was done using json
commentForm.after(commentAlert);
if (!response.status) {
//should not trigger at all, if all bad requests return the right http status code
//i.e. <> 200 success => thus triggering posting.fail()
//leave this check just in case
commentAlert.stop().css('opacity', 1).text('Error: ' + response.message).fadeIn(30).fadeOut(5000);
return;
}
if (response.status) {
commentAlert.css('color', 'green').empty().append(document.createTextNode( response.message )).fadeIn(30);
var newMedia = "<div class='comment comment-level-{{comment.level|e}} comment-flag-new' data-level='{{comment.level}}' data-id='{{comment.id}}' >" +
"<div class='comment-left'>" +
"<img class='comment-object' src='https://www.gravatar.com/avatar/{{comment.email|trim|lower|md5}}?d=identicon' alt='user icon'>" +
"</div>" +
"<div class='comment-body'>" +
"<div class='comment-heading'>" +
"<div class='comment-title'><h4>{{comment.title}}</h4></div>" +
"<div class='comment-reply'><a class='comment-add-reply' href='#'><i class='fa fa-reply' title='{{'PLUGIN_COMMENTS.ADD_REPLY'|t}}'></i> {{'PLUGIN_COMMENTS.REPLY'|t}}</a></div>" +
"<div class='comment-meta'>{{'PLUGIN_COMMENTS.WRITTEN_ON'|t}} {{comment.date|e}} {{'PLUGIN_COMMENTS.BY'|t}} {{comment.author}}</div>" +
"</div>" +
"<div class='comment-text' >" +
"{{comment.text}}" +
"</div>" +
"{{nested}}" +
"</div>" +
"</div>";
newMedia = newMedia.replace(new RegExp(escapeRegExp("{{comment.id}}"), 'g'), response.data.id);
newMedia = newMedia.replace(new RegExp(escapeRegExp("{{comment.level|e}}"), 'g'), ownLevel);
newMedia = newMedia.replace(new RegExp(escapeRegExp("{{comment.level}}"), 'g'), ownLevel);
newMedia = newMedia.replace(new RegExp(escapeRegExp("{{comment.email|trim|lower|md5}}"), 'g'), response.data.hash);
newMedia = newMedia.replace(new RegExp(escapeRegExp("{{parent_id}}"), 'g'), response.data.parent_id);
newMedia = newMedia.replace(new RegExp(escapeRegExp("{{comment.title}}"), 'g'), response.data.title);
newMedia = newMedia.replace(new RegExp(escapeRegExp("{{comment.text}}"), 'g'), response.data.text);
newMedia = newMedia.replace(new RegExp(escapeRegExp("{{comment.author}}"), 'g'), response.data.name);
newMedia = newMedia.replace(new RegExp(escapeRegExp("{{comment.date|e}}"), 'g'), response.data.date);
newMedia = newMedia.replace(new RegExp(escapeRegExp("{{nested}}"), 'g'), '');
newMedia = newMedia.replace(new RegExp(escapeRegExp("{{'PLUGIN_COMMENTS.ADD_REPLY'|t}}"), 'g'), response.data.ADD_REPLY);
newMedia = newMedia.replace(new RegExp(escapeRegExp("{{'PLUGIN_COMMENTS.REPLY'|t}}"), 'g'), response.data.REPLY);
newMedia = newMedia.replace(new RegExp(escapeRegExp("{{'PLUGIN_COMMENTS.WRITTEN_ON'|t}}"), 'g'), response.data.WRITTEN_ON);
newMedia = newMedia.replace(new RegExp(escapeRegExp("{{'PLUGIN_COMMENTS.BY'|t}}"), 'g'), response.data.BY);
if ($( "div[data-id='" + response.data.parent_id + "']" ).length > 0) {
$( "div[data-id='" + response.data.parent_id + "']" ).first().after(newMedia);
} else {
$( "#comments" ).prepend(newMedia);
}
}
setTimeout(function () {
commentForm.slideUp();
commentAlert.fadeOut(5000);
}, 5000);
});
posting.fail(function (status, error, title) {
//alert('error');
//console.log("Response Data (fail)", JSON.parse(JSON.stringify(status)));
commentForm.after(commentAlert);
commentAlert.show();
commentAlert.empty().append("<p>Error: </p>");
commentAlert.append("<p>" + JSON.stringify(status) + "</p>");
commentAlert.append("<p>" + JSON.stringify(error) + "</p>");
commentAlert.append("<p>" + JSON.stringify(title) + "</p>");
});
posting.always(function () {
//alert("finished, be it successful or not");
});
});
});
44 changes: 44 additions & 0 deletions class/Comment.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
<?php

namespace Grav\Plugin;

class Comment
{
private $id = 0;
private $value = array();
private $parent = null;
private $children = array();

public function __construct($id, $content) {
$this->id = $id;
$this->value = $content;
}

public function addItem($obj, $key = null) {
}

public function deleteItem($key) {
}

public function getItem($key) {
}

public function getContent($level = 0) {
$this->value['level'] = $level;
$comments[] = $this->value;

foreach($this->children as $child) {
//$comments[] = $child->getContent($level + 1); //produces nested result array.
$comments = array_merge($comments, $child->getContent($level + 1)); //produces flat result array.
}
return $comments;
}

public function setParent($parent) {
$this->parent = $parent;
}
public function addSubComment($obj) {
$this->children[] = $obj;
}

}
Loading