Merge https://github.com/codeshell/grav-plugin-comments into develop
This commit is contained in:
		
						commit
						be0eca0ff5
					
				
					 10 changed files with 1071 additions and 391 deletions
				
			
		
							
								
								
									
										86
									
								
								assets/comments.css
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										86
									
								
								assets/comments.css
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,86 @@
 | 
			
		|||
/*
 | 
			
		||||
===============================================================================================================================
 | 
			
		||||
Comments Plugin Styles
 | 
			
		||||
===============================================================================================================================
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
.comment {
 | 
			
		||||
	margin-top: 0px;
 | 
			
		||||
  width:100%;
 | 
			
		||||
}
 | 
			
		||||
.comment:first-child {
 | 
			
		||||
  margin-top: 0px;
 | 
			
		||||
}
 | 
			
		||||
.comment,
 | 
			
		||||
.comment-body {
 | 
			
		||||
  zoom: 1;
 | 
			
		||||
}
 | 
			
		||||
.comment-body {
 | 
			
		||||
  overflow: hidden;
 | 
			
		||||
  margin-left: 10px;
 | 
			
		||||
}
 | 
			
		||||
.comment-object {
 | 
			
		||||
  display: block;
 | 
			
		||||
}
 | 
			
		||||
.comment-right,
 | 
			
		||||
.comment > .pull-right {
 | 
			
		||||
  padding-left: 10px;
 | 
			
		||||
}
 | 
			
		||||
.comment-left,
 | 
			
		||||
.comment > .pull-left {
 | 
			
		||||
  padding-right: 10px;
 | 
			
		||||
}
 | 
			
		||||
.comment-middle {
 | 
			
		||||
  vertical-align: middle;
 | 
			
		||||
}
 | 
			
		||||
.comment-bottom {
 | 
			
		||||
  vertical-align: bottom;
 | 
			
		||||
}
 | 
			
		||||
.comment-heading {
 | 
			
		||||
  margin-top: 0px;
 | 
			
		||||
  margin-bottom: 5px;
 | 
			
		||||
}
 | 
			
		||||
.comment-meta {
 | 
			
		||||
	font-size: small;
 | 
			
		||||
}
 | 
			
		||||
.comment-text {
 | 
			
		||||
	clear: both;
 | 
			
		||||
}
 | 
			
		||||
.comment-list {
 | 
			
		||||
  padding-left: 0px;
 | 
			
		||||
  list-style: none;
 | 
			
		||||
}
 | 
			
		||||
.comment-flag-new {
 | 
			
		||||
	background-color: lightcyan;
 | 
			
		||||
}
 | 
			
		||||
.comment-wrapper {
 | 
			
		||||
  display: -webkit-box;
 | 
			
		||||
  display: -moz-box;
 | 
			
		||||
  display: -ms-flexbox;
 | 
			
		||||
  display: -webkit-flex;
 | 
			
		||||
  display: flex;
 | 
			
		||||
}
 | 
			
		||||
.comment-avatar {
 | 
			
		||||
  width: 20px;
 | 
			
		||||
  height: 20px;
 | 
			
		||||
  margin-left: -10px;
 | 
			
		||||
  margin-right:5px;
 | 
			
		||||
  vertical-align: middle;
 | 
			
		||||
}
 | 
			
		||||
/*.comment-thread-line:hover {
 | 
			
		||||
  border-left:3px solid #1BB3E9;
 | 
			
		||||
}*/
 | 
			
		||||
.comment-thread-top {
 | 
			
		||||
  margin-top:20px;
 | 
			
		||||
}
 | 
			
		||||
.comment-thread {
 | 
			
		||||
  float: left;
 | 
			
		||||
  border-left:3px solid #444;
 | 
			
		||||
  margin-left:10px;
 | 
			
		||||
}
 | 
			
		||||
.comment-footer {
 | 
			
		||||
  font-size: small;
 | 
			
		||||
}
 | 
			
		||||
.comment-reply {
 | 
			
		||||
  display: inline;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										216
									
								
								assets/comments.js
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										216
									
								
								assets/comments.js
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,216 @@
 | 
			
		|||
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 parent = 0;
 | 
			
		||||
        var ownLevel = 0;
 | 
			
		||||
        if ($(this).parents('.comment').length > 0) {
 | 
			
		||||
            parent = $(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, { parent: parent, data: data }, null, 'json');
 | 
			
		||||
        var posting = $.post(url, data + '&parent=' + parent, 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>";*/
 | 
			
		||||
                var newMedia = `<div id="comment-{{comment.id}}" class="comment comment-level-{{comment.level|e}}" data-id="{{comment.id}}" itemtype="http://schema.org/UserComments">
 | 
			
		||||
				<header class="comment-heading">
 | 
			
		||||
					<img class="comment-avatar" src="https://www.gravatar.com/avatar/{{comment.email|trim|lower|md5}}?size=20&d=identicon" alt="user icon">
 | 
			
		||||
					<span class="comment-meta">
 | 
			
		||||
					{% if comment.site %}
 | 
			
		||||
						<a href="{{comment.site}}">{{comment.author}}</a>
 | 
			
		||||
					{% else %}
 | 
			
		||||
						{{comment.author}}
 | 
			
		||||
					{% endif %}
 | 
			
		||||
					<a href="{{uri.url(true)}}#comment-{{comment.id}}" title="Link to this comment" itemprop="url">
 | 
			
		||||
						<time class="comment-date" datetime="{{comment.date|e}}" itemprop="commentTime">
 | 
			
		||||
						{{comment.date|nicetime(false)}}
 | 
			
		||||
						</time>
 | 
			
		||||
					</a>
 | 
			
		||||
					</span>
 | 
			
		||||
				</header>
 | 
			
		||||
				<div class="comment-body">
 | 
			
		||||
					<div class="comment-text" >
 | 
			
		||||
					{{comment.text}}
 | 
			
		||||
					</div>
 | 
			
		||||
					{{nested}}
 | 
			
		||||
					<div class="comment-footer">
 | 
			
		||||
					<span class="comment-reply">
 | 
			
		||||
						{% if grav.twig.commenting_enabled %}
 | 
			
		||||
						<a class="comment-add-reply" href="#"><i class="fa fa-reply" title="{{'PLUGIN_COMMENTS.ADD_REPLY'|t}}"></i> {{'PLUGIN_COMMENTS.REPLY'|t}}</a>
 | 
			
		||||
						{% endif %}
 | 
			
		||||
						{% if grav.user.access.admin.super %}
 | 
			
		||||
						<a class="comment-delete" href="#"><i class="fa fa-trash" title="{{'PLUGIN_COMMENTS.DELETE_COMMENT'|t}}"></i> {{'PLUGIN_COMMENTS.DELETE'|t}}</a>
 | 
			
		||||
						{% endif %}
 | 
			
		||||
					</span>
 | 
			
		||||
					</div>
 | 
			
		||||
				</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}}"), 'g'), response.data.parent);
 | 
			
		||||
                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.site}}"), 'g'), response.data.site);
 | 
			
		||||
                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);
 | 
			
		||||
                if ($("div[data-id='" + response.data.parent + "']").length > 0) {
 | 
			
		||||
                    $("div[data-id='" + response.data.parent + "']").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");
 | 
			
		||||
        });
 | 
			
		||||
    });
 | 
			
		||||
});
 | 
			
		||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue