-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
No Ticket : Add current version of comment-section.html
- Loading branch information
Showing
2 changed files
with
276 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,7 @@ | ||
# jekyll-comments-google-forms | ||
Files necessary to add comments to Jekyll through use of Google Forms: https://jdvp.me/articles/Google-Forms-Jekyll-Comments | ||
|
||
Files necessary to add comments to Jekyll through use of Google Forms. | ||
|
||
To see how to use this file in your Jekyll project, take a look at this article I wrote: [Using Google Forms for Jekyll Comments] | ||
|
||
[Using Google Forms for Jekyll Comments]: https://jdvp.me/articles/Google-Forms-Jekyll-Comments |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,270 @@ | ||
{% if site.comment-read %} | ||
<!-- Load Required 3rd-Party Scripts. We use the following: | ||
* jquery for DOM manipulation | ||
* jquery-csv for parsing Google Sheets CSV data to JSON | ||
* validator for escaping user-entered comments to prevent malicious code input in comments | ||
Make sure to update these to the latest versions every once in a while. | ||
--> | ||
<script | ||
src="https://code.jquery.com/jquery-3.6.0.min.js" | ||
integrity="sha256-/xUj+3OJU5yExlq6GSYGSHk7tPXikynS7ogEvDej/m4=" | ||
crossorigin="anonymous"></script> | ||
<script | ||
src="https://cdnjs.cloudflare.com/ajax/libs/jquery-csv/1.0.11/jquery.csv.min.js" | ||
integrity="sha512-Y8iWYJDo6HiTo5xtml1g4QqHtl/PO1w+dmUpQfQSOTqKNsMhExfyPN2ncNAe9JuJUSKzwK/b6oaNPop4MXzkwg==" | ||
crossorigin="anonymous"></script> | ||
<script | ||
src="https://cdnjs.cloudflare.com/ajax/libs/validator/13.5.2/validator.min.js" | ||
integrity="sha512-vZEoK8xRncku4g5GANHh5zobUjeCMbZkSEahrADeAcRlk/1Ignf8sAKojkV4RZLkPw145+ILJFisI2pnjsPtGQ==" | ||
crossorigin="anonymous"></script> | ||
|
||
<!-- Our own JS starts here--> | ||
<script> | ||
var thisPageUrl = "{{ include.url }}"; | ||
var visibleComments = []; | ||
|
||
/* Format the comment's date to our desired format */ | ||
function formatDate(stringDate) { | ||
var date = new Date(stringDate); | ||
var dateOptions = { year: 'numeric', month: 'long', day: 'numeric'}; | ||
var timeOptions = { hour: 'numeric', minute: 'numeric' }; | ||
return `${date.toLocaleDateString("en-us", dateOptions)} at ${date.toLocaleTimeString("en-us", timeOptions)}`; | ||
}; | ||
|
||
/* Called when the comments have been loaded or relaoded. | ||
Comments that we have already displayed on the page will be ignored */ | ||
function displayComments(comments) { | ||
/* if we have no comments, show the 'no comments available' section */ | ||
if (comments == null || comments === "") { | ||
if (visibleComments.length == 0) { | ||
$("#no-comments").show(); | ||
} | ||
return; | ||
} | ||
|
||
/* Add headers so json objects are named properly */ | ||
comments = `timestamp,name,comment,isAuthor\n${comments}`; | ||
commentList = $.csv.toObjects(comments); | ||
|
||
/* iterate over each comment that came from Google Sheets */ | ||
commentList.forEach(function(element) { | ||
/* don't re-add existing comments */ | ||
if (visibleComments.includes(JSON.stringify(element))) { | ||
return; | ||
} | ||
|
||
/* If the author was the one who commented back, add this 'verified' logic */ | ||
var verifiedAuthorTag = ""; | ||
if (element.isAuthor === "TRUE") { | ||
verifiedAuthorTag = " <strong>(Author)</strong>"; | ||
} | ||
|
||
/* Create the new item using HTML and append it to the user-visible comment section */ | ||
var newItem = $(` | ||
<div class="comment-item"> | ||
<p class="commenter-name">${validator.escape(element.name)}${verifiedAuthorTag}<small>${formatDate(element.timestamp)}</small></p> | ||
<div> | ||
<p>${validator.escape(element.comment).replace(new RegExp('\r?\n','g'), '<br />')}</p> | ||
</div> | ||
</div> | ||
`).hide(); | ||
$("#commentSection").append(newItem); | ||
newItem.fadeIn(); | ||
visibleComments.push(JSON.stringify(element)); | ||
|
||
/* Hide the 'no comments available' section since we have added a comment */ | ||
$("#no-comments").hide(); | ||
}); | ||
}; | ||
|
||
/* Calls to the Google Sheets gviz API to load the comment data | ||
Since we are storing comments for all of our blog articles in one sheet, we filter | ||
by page URL. */ | ||
function reloadComments() { | ||
/* | ||
Use SQL in the gviz URL to load the correct csv. | ||
In this implementation, columns are mapped to the following: | ||
A - timestamp, the time the comment was left | ||
B - page url, the page the comment was left on | ||
C - name, the text left in the comment name field | ||
D - comment, the text left in the comment field | ||
E - isAuthor, boolean indicating if the comment was left by the actual author | ||
*/ | ||
var sqlStatement = encodeURIComponent(`SELECT A, C, D, E WHERE B = '${thisPageUrl}'`); | ||
fetch(`{{ site.comment-read }}/gviz/tq?tqx=out:csv&sheet=comments&tq=${sqlStatement}&headers=0`) | ||
.then(response => response.text()) | ||
.then(response => displayComments(response)); | ||
}; | ||
|
||
/* Reload the comments when the page first loads */ | ||
reloadComments(); | ||
|
||
/* encodes the form data for http transport */ | ||
const encodeFormData = (data) => { | ||
return Object.keys(data) | ||
.map(key => encodeURIComponent(key) + '=' + encodeURIComponent(data[key])) | ||
.join('&'); | ||
}; | ||
|
||
/* Posts a comment */ | ||
function postComment() { | ||
var username = $("#comment-name").val(); | ||
var comment = $("#comment-comment").val(); | ||
|
||
fetch(`{{ site.comment-post }}/formResponse`, { | ||
method: 'POST', | ||
mode: 'no-cors', | ||
headers: { | ||
"Content-Type": "application/x-www-form-urlencoded" | ||
}, | ||
body: encodeFormData({ | ||
"{{ site.comment-post-fields[0] }}" : thisPageUrl, | ||
"{{ site.comment-post-fields[1] }}" : username, | ||
"{{ site.comment-post-fields[2] }}" : comment | ||
}) | ||
}).then(response => { | ||
$("#comment-name").val(''); | ||
$("#comment-comment").val(''); | ||
reloadComments(); | ||
}) | ||
.catch(error => {console.log(error);}); | ||
|
||
return false; | ||
}; | ||
</script> | ||
<!-- | ||
HTML for displaying the actual comment section. | ||
It has a state for oth when the article has comments and when it does not. | ||
--> | ||
<h4 class="post-subtitle">Comments</h4> | ||
<div id="commentSection" class="comments"> | ||
<div id="no-comments" class="post-info"> | ||
<p>There are currently no comments on this article, be the first to add one below</p> | ||
</div> | ||
</div> | ||
<h4 class="post-subtitle">Add a Comment</h4> | ||
<div class="comments"> | ||
<div class="post-info"> | ||
<p>Note that I may remove comments for any reason, so try to be civil. If you are looking for a response to your comment, either leave your email address or check back on this page periodically.</p> | ||
</div> | ||
<div class="comments-form"> | ||
<form onsubmit="return postComment()" id="comment-form" autocomplete="off"> | ||
<ul> | ||
<li><input id="comment-name" name="username" type="text" placeholder="Name" required="" value=""></li> | ||
<li><textarea id="comment-comment" name="comment" placeholder="Comment" required=""></textarea></li> | ||
<li><input id="comment-submit" type="submit" value="Post"></li> | ||
</ul> | ||
</form> | ||
</div> | ||
</div> | ||
<!-- | ||
Styling information. | ||
This might typically be in an scss file but is added here so only a single | ||
file needs to be added to a project trying to implement this feature. | ||
--> | ||
<style> | ||
@import url("https://fonts.googleapis.com/css?family=Source+Sans+Pro"); | ||
.comment-item { | ||
position: relative; | ||
padding: 0.5em 2.5em; | ||
background: white; | ||
font-family: "Source Sans Pro", sans-serif; | ||
width: 95%; | ||
margin: 1em auto; | ||
box-shadow: 0px 0px 2px 2px rgba(0, 0, 0, 0.1); | ||
border-radius: 8px; | ||
} | ||
.comment-item:after { | ||
content: ""; | ||
position: relative; | ||
display: block; | ||
clear: both; | ||
} | ||
.comment-item p { | ||
line-height: 1.6; | ||
} | ||
.comment-item small { | ||
padding-left: 0.7em; | ||
color: #999; | ||
font-size: 0.8em; | ||
} | ||
.commenter-name { | ||
color: #367588; | ||
text-decoration: none; | ||
font-size: 1em; | ||
font-weight: 700; | ||
} | ||
.commenter-name strong { | ||
color: #e91e63; | ||
text-decoration: none; | ||
font-size: 1em; | ||
font-weight: 700; | ||
} | ||
.comments { | ||
border-top: 0.5px solid #e5e5e5; | ||
padding-top: 1rem; | ||
position: relative; | ||
} | ||
.comments-form { | ||
margin-left: 1em; | ||
margin-right: 1em; | ||
width: 95%; | ||
font-family: "Source Sans Pro", sans-serif; | ||
} | ||
.comments-form ul { | ||
list-style: none; | ||
margin-left: -40px; | ||
} | ||
.comments-form ul li { | ||
margin-bottom: 15px; | ||
} | ||
.comments-form ul li input[type='submit'] { | ||
border: 0; | ||
border-radius: 8px; | ||
padding: 10px 10px; | ||
background: #9ccc65; | ||
color: #fff; | ||
font-family: "Source Sans Pro", sans-serif; | ||
font-weight: bold; | ||
font-size: 0.9em; | ||
text-transform: uppercase; | ||
margin-bottom: 20px; | ||
width: 25%; | ||
outline-style: none; | ||
} | ||
.comments-form ul li input[type='text'], .comments-form ul li textarea { | ||
width: 50%; | ||
padding: 10px; | ||
border: 0; | ||
border-radius: 8px; | ||
background: #f7f7f7; | ||
font-family: "Source Sans Pro", sans-serif; | ||
} | ||
.comments-form ul li input[type='text']::-webkit-input-placeholder, .comments-form ul li textarea::-webkit-input-placeholder { | ||
font-family: "Source Sans Pro", sans-serif; | ||
} | ||
.comments-form ul li input[type='text']::-moz-placeholder, .comments-form ul li textarea::-moz-placeholder { | ||
font-family: "Source Sans Pro", sans-serif; | ||
} | ||
.comments-form ul li input[type='text']:-ms-input-placeholder, .comments-form ul li textarea:-ms-input-placeholder { | ||
font-family: "Source Sans Pro", sans-serif; | ||
} | ||
.comments-form ul li input[type='text']::-ms-input-placeholder, .comments-form ul li textarea::-ms-input-placeholder { | ||
font-family: "Source Sans Pro", sans-serif; | ||
} | ||
.comments-form ul li input[type='text']::placeholder, .comments-form ul li textarea::placeholder { | ||
font-family: "Source Sans Pro", sans-serif; | ||
} | ||
.comments-form ul li input[type='text']:focus, .comments-form ul li textarea:focus { | ||
background: #fff; | ||
font-family: "Source Sans Pro", sans-serif; | ||
} | ||
.comments-form ul li textarea { | ||
width: 100%; | ||
height: 80px; | ||
resize: vertical; | ||
min-height: 80px; | ||
} | ||
</style> | ||
{% endif %} |