Fork me on GitHub

EasyPageComments

By Mike "Pomax" Kamermans

I needed some simple but full-featured, login-less comments for several pages I'm running for presenting loose technology snippets to the world that I don't want to present through some CMS because the styling's going to be completely different, or the subject is just not related to my specifically-purposed websites. As such, I needed it to be modular, and require almost no work to drop into newly written pages. Looking at what I already had written for my Primer on Bezier curves I figured I already had something close to what I needed, just a bit too part-of-the-page, so I lifted it out, cleaned the code up, and added some of the features that were still missing, ending up with exactly what I need: A simple but full featured "drop it in, and glue it on with less than 10 lines of code" commenting system.

The styling's all CSS, so style it to look like whatever you think looks best, and get some comments going on for pages that are just random pages, rather than CMS-ed pages.

Features:

"Installing" EasyPageComments

There's no real installation to speak of - just grab EasyPageComments from github, or just download a zip file with the code:

After obtaining all the files, drop the EasyPageComments.php file (and optionally the EasyPageComments.js file) in the same dir as your page. Then depending on your preferred method of use, either:

a) add

require_once("EasyPageComments.php");

at the top of your page, in a php block, or

b) add

<script type="text/javascript" src="EasyPageComments.js"></script>

to your page's <head> block.

Generating the comments

The PHP way

Generating the comment list could not be easier. Okay, no, that's a lie, I guess it could be. But it's pretty damn easy. Just find the place where you want the comments to show up, and insert:

<?php $EasyPageComments->createCommentsList(); ?>
<?php $EasyPageComments->createCommentForm(); ?>

This will, in fact, store and list messages for "the current page", which is whatever your URL bar shows, minus the domain name. This is super convenient, but it also makes moving the page a little bit of work. Which is inconvenient. To make life easier again, the function can also take a pagename argument:

<?php $EasyPageComments->createCommentsList("My Page Name"); ?>
<?php $EasyPageComments->createCommentForm("My Page Name"); ?>

And now messages are stored and retrieved using that page name, rather than getting the page name from the URL. Handy-dandy.

The upside

Super-no-work-at-all solution, requiring one line to include the EasyPageComments.php package, one line to inject the comment list, and one line to inject the comment posting form.

Does not rely in JavaScript in any way, so it even works when people have NoScript and the like turned on.

The downside

Does not rely on JavaScript in any way, so posting a new comment reloads the page. Your users may also not be able to reply to other user's posts at the moment, as this relies on JavaScript being available at the moment.

The JavaScript way (recommended, really)

EasyPageComments also works with plain .html pages, in case you don't want to give your pages a .php extension. Simply have some container elements on your page:

<div id="id-for-list-element"></div>
<div id="id-for-comment-form"></div>

And then implement these two functions for injecting the comments list and post form into your web page:

function showEasyPageComments(setname, data) {
  document.getElementById("id-for-list-element").innerHTML = data;
}
function showEasyPageCommentForm(setname, data) {
  document.getElementById("id-for-comment-form).innerHTML = data;
} 

And then trigger them (at page load or DOMReady or something) by calling:

EasyPageComments.createCommentsList("My Page Name");
EasyPageComments.createCommentForm("My Page Name");

Note that the "id-for-list-element" and "id-for-comment-form" are up to you. You can use whatever names you want, or even use some other form of identifying the elements you want the list and comment form generated in. The important part is that showEasyPageComments(setname, data) and showEasyPageCommentForm(setname, data) have some body code that lets them put data into the containers you dedicated to them on your page.

Also note that because you can have multiple comment forms on the page, there is a setname value that comes along with the data. If you have multiple comment sections, it's a good idea to make sure the HTML element containers you use indicate which set they're for, so you can do things like:

function showEasyPageComments(setname, data) {
  document.getElementById("list-for-"+setname).innerHTML = data;
}

As an illustration, this page uses the following code for the JavaScript version of EasyPageComments:

function showEasyPageComments(setname, data) {
  document.getElementById('EasyPageComments').innerHTML = data; }

function showEasyPageCommentForm(setname, data) {
  document.getElementById('EasyPageCommentForm').innerHTML = data; }

function addEasyPageComments() {
  EasyPageComments.createCommentsList('EasyPageComments');
  EasyPageComments.createCommentForm('EasyPageComments'); }

document.addEventListener("DOMContentLoaded", addEasyPageComments, false)

Because the javascript call makes it impossible for PHP to check which page it was called for (since you're calling the script directly, rather than as part of a specific page-request to the server), the page name is mandatory when using JavaScript.

Note that the JavaScript approach refreshes the comments list after posting a new comment, so make sure that showEasyPageComments(data) overwrites whatever is in your list container element, or things will look wrong for someone posting a comment.

The upside

Loading and posting is dynamic. You can add the comments block to your page only when the user requests comment functionality, and posting is handled in-place, without the page needing to be reloaded just to show the new comment, or errors with a faulty post.

The downside

If people block JavaScript, they won't get comment functionality until they unblock it. It's also a tiny bit more work to make it do its thing, although given the code already provided, it's about as much of a no-brainer to get things to work =)

A demonstrator

A demonstrator comments list for this page, inserted with PHP (and styled with this stylesheet):

PostyMan
Monday, October 31st 2011 - 7:09 am (GMT-7)
Feirst poast!
reply
Pomax
Monday, October 31st 2011 - 7:11 am (GMT-7)
Using the 'reply' link makes your message a reply to a specific message. Replies create comment threads, which can be indented (if so desired) by using a CSS margin. Additionally, messages by the page owner can be colored differently from regular messages so that they stand out.
reply
PostyMan
Monday, October 31st 2011 - 7:22 am (GMT-7)
The more a thread is replied to, the deeper it nests. Ideally this doesn't happen too much, because comments are generally not intended as forum, but just in case you do spark the kind of controversy that requires threading, it's there.
reply
Blah
Wednesday, September 13th 2017 - 2:07 am (GMT-7)
Give a kiss to your hand (left hand)
2.- Say the name of your love.
3.- Close your hand
4.- Say the name of a weekday
5.- Say your name
6.- Open your hand
7.- paste this to 15 comments and the day you said (step # 4 he/she will tell you that they like you and maybe even engages or maybe kiss you. If you don't do it something will go wrong in about an hour Thursday
reply
Blah
Wednesday, September 13th 2017 - 2:04 am (GMT-7)
Give a kiss to your hand (left hand)
2.- Say the name of your love.
3.- Close your hand
4.- Say the name of a weekday
5.- Say your name
6.- Open your hand
7.- paste this to 15 comments and the day you said (step # 4 he/she will tell you that they like you and maybe even engages or maybe kiss you. If you don't do it something will go wrong in about an hour Thursday
reply
PostyMan
Monday, October 31st 2011 - 7:24 am (GMT-7)
Anyone can leave comments without needing to log in; all they have to do is get the security question right. This question and its posssible answers can be set in the EasyPageComments.php file, at the top. For this page, for instance, the correct answer is "10", but if you write it as "ten" or as "10" (using full-width unicode numbers) then those are acceptable answers, too, and your message will get posted.
reply
ポスちー万
Monday, October 31st 2011 - 7:27 am (GMT-7)
Which brings us to the matter of Unicode text: Use however much of it as you like. A non-ascii username, for instance, is just fine. And why wouldn't it be, this is the future, after all, and of course we all know that assuming ascii input was something they did in the dark ages. Right?
reply
Pomax
Monday, October 31st 2011 - 7:32 am (GMT-7)
If only the future was that nice. A lot of people still think that "ascii is fine", even though a lot of people in English speaking countries have names that cannot be spelled using just the ascii range. Luckily, SQLite does not care, so we don't suffer from that problem in this commenting package. 日本語など中国語など書いても当然によい。 ...That means you can write Japanese or Chinese without any problems.
reply
Blah
Wednesday, September 13th 2017 - 2:04 am (GMT-7)
Give a kiss to your hand (left hand)
2.- Say the name of your love.
3.- Close your hand
4.- Say the name of a weekday
5.- Say your name
6.- Open your hand
7.- paste this to 15 comments and the day you said (step # 4 he/she will tell you that they like you and maybe even engages or maybe kiss you. If you don't do it something will go wrong in about an hour Thursday
reply
Blah
Wednesday, September 13th 2017 - 2:05 am (GMT-7)
Give a kiss to your hand (left hand)
2.- Say the name of your love.
3.- Close your hand
4.- Say the name of a weekday
5.- Say your name
6.- Open your hand
7.- paste this to 15 comments and the day you said (step # 4 he/she will tell you that they like you and maybe even engages or maybe kiss you. If you don't do it something will go wrong in about an hour Thursday
reply
Blah
Wednesday, September 13th 2017 - 2:04 am (GMT-7)
Give a kiss to your hand (left hand)
2.- Say the name of your love.
3.- Close your hand
4.- Say the name of a weekday
5.- Say your name
6.- Open your hand
7.- paste this to 15 comments and the day you said (step # 4 he/she will tell you that they like you and maybe even engages or maybe kiss you. If you don't do it something will go wrong in about an hour Thursday
reply
Blah
Wednesday, September 13th 2017 - 2:06 am (GMT-7)
Give a kiss to your hand (left hand)
2.- Say the name of your love.
3.- Close your hand
4.- Say the name of a weekday
5.- Say your name
6.- Open your hand
7.- paste this to 15 comments and the day you said (step # 4 he/she will tell you that they like you and maybe even engages or maybe kiss you. If you don't do it something will go wrong in about an hour Thursday
reply
Blah
Wednesday, September 13th 2017 - 2:05 am (GMT-7)
Give a kiss to your hand (left hand)
2.- Say the name of your love.
3.- Close your hand
4.- Say the name of a weekday
5.- Say your name
6.- Open your hand
7.- paste this to 15 comments and the day you said (step # 4 he/she will tell you that they like you and maybe even engages or maybe kiss you. If you don't do it something will go wrong in about an hour Thursday
reply
Blah
Wednesday, September 13th 2017 - 2:05 am (GMT-7)
Give a kiss to your hand (left hand)
2.- Say the name of your love.
3.- Close your hand
4.- Say the name of a weekday
5.- Say your name
6.- Open your hand
7.- paste this to 15 comments and the day you said (step # 4 he/she will tell you that they like you and maybe even engages or maybe kiss you. If you don't do it something will go wrong in about an hour Thursday
reply
Blah
Wednesday, September 13th 2017 - 2:06 am (GMT-7)
Give a kiss to your hand (left hand)
2.- Say the name of your love.
3.- Close your hand
4.- Say the name of a weekday
5.- Say your name
6.- Open your hand
7.- paste this to 15 comments and the day you said (step # 4 he/she will tell you that they like you and maybe even engages or maybe kiss you. If you don't do it something will go wrong in about an hour Thursday
reply
PostyMan
Monday, October 31st 2011 - 7:34 am (GMT-7)
You can also be notified by email whenever someone posts a comment, because you're not going to check your older pages every day for new comments. Nor would you want to set up RSS monitoring for them (why poll a site RSS every hour when it'll only receive a comment every few days?). This can be enabled or disabled in the EasyPageComments.php file too.
reply
Pomax
Friday, November 4th 2011 - 7:23 pm (GMT-7)
And last but not least, EasyPageComments is hash aware, so if you want to link to a specific post, even if you rely on the JavaScript approach to inject comments after page loading, EasyPageComments.js ensures that the page gets jumped to the request comment once the comments listing is generated.
reply
<script type="text/javascript"> alert("hi") </script>
Monday, November 14th 2011 - 6:48 am (GMT-8)
<script type="text/javascript">
alert("hi")
</script>
reply
Pomax
Monday, November 14th 2011 - 10:14 am (GMT-8)
hehe, yes, that gets securified. HTML, JavaScript and SQL are sanitized before insertion, and angled brackets never get converted back to real brackets (so HTML is demoted to text with html entities).
reply
Mr Magoo
Sunday, July 23rd 2017 - 5:42 am (GMT-7)
testme
reply
Blah
Wednesday, September 13th 2017 - 2:07 am (GMT-7)
Give a kiss to your hand (left hand)
2.- Say the name of your love.
3.- Close your hand
4.- Say the name of a weekday
5.- Say your name
6.- Open your hand
7.- paste this to 15 comments and the day you said (step # 4 he/she will tell you that they like you and maybe even engages or maybe kiss you. If you don't do it something will go wrong in about an hour Thursday
reply
etes
Sunday, July 30th 2017 - 10:52 pm (GMT-7)
dsdasd
reply
oğuzhan cengiz
Sunday, July 30th 2017 - 10:52 pm (GMT-7)
test
reply
Blah
Wednesday, September 13th 2017 - 2:08 am (GMT-7)
Give a kiss to your hand (left hand)
2.- Say the name of your love.
3.- Close your hand
4.- Say the name of a weekday
5.- Say your name
6.- Open your hand
7.- paste this to 15 comments and the day you said (step # 4 he/she will tell you that they like you and maybe even engages or maybe kiss you. If you don't do it something will go wrong in about an hour Thursday
reply
hallow0rld
Monday, July 31st 2017 - 7:06 pm (GMT-7)
rwrwearerwawwatistis
reply
Blah
Wednesday, September 13th 2017 - 2:07 am (GMT-7)
Give a kiss to your hand (left hand)
2.- Say the name of your love.
3.- Close your hand
4.- Say the name of a weekday
5.- Say your name
6.- Open your hand
7.- paste this to 15 comments and the day you said (step # 4 he/she will tell you that they like you and maybe even engages or maybe kiss you. If you don't do it something will go wrong in about an hour Thursday
reply
hallow0rld
Monday, July 31st 2017 - 7:28 pm (GMT-7)
rwrwearerwawwatistis
reply
ss
Monday, September 11th 2017 - 4:17 am (GMT-7)
asdsd1wed
reply
Blah
Wednesday, September 13th 2017 - 2:08 am (GMT-7)
Give a kiss to your hand (left hand)
2.- Say the name of your love.
3.- Close your hand
4.- Say the name of a weekday
5.- Say your name
6.- Open your hand
7.- paste this to 15 comments and the day you said (step # 4 he/she will tell you that they like you and maybe even engages or maybe kiss you. If you don't do it something will go wrong in about an hour Thursday
reply
ss
Tuesday, September 12th 2017 - 6:14 am (GMT-7)
test
reply
Blah
Wednesday, September 13th 2017 - 2:03 am (GMT-7)
Give a kiss to your hand (left hand)
2.- Say the name of your love.
3.- Close your hand
4.- Say the name of a weekday
5.- Say your name
6.- Open your hand
7.- paste this to 15 comments and the day you said (step # 4 he/she will tell you that they like you and maybe even engages or maybe kiss you. If you don't do it something will go wrong in about an hour Thursday
reply
Blah
Wednesday, September 13th 2017 - 2:03 am (GMT-7)
Give a kiss to your hand (left hand)
2.- Say the name of your love.
3.- Close your hand
4.- Say the name of a weekday
5.- Say your name
6.- Open your hand
7.- paste this to 15 comments and the day you said (step # 4 he/she will tell you that they like you and maybe even engages or maybe kiss you. If you don't do it something will go wrong in about an hour Thursday
reply
Blah
Wednesday, September 13th 2017 - 2:08 am (GMT-7)
Give a kiss to your hand (left hand)
2.- Say the name of your love.
3.- Close your hand
4.- Say the name of a weekday
5.- Say your name
6.- Open your hand
7.- paste this to 15 comments and the day you said (step # 4 he/she will tell you that they like you and maybe even engages or maybe kiss you. If you don't do it something will go wrong in about an hour Thursday
reply
Blah
Wednesday, September 13th 2017 - 2:09 am (GMT-7)
Give a kiss to your hand (left hand)
2.- Say the name of your love.
3.- Close your hand
4.- Say the name of a weekday
5.- Say your name
6.- Open your hand
7.- paste this to 15 comments and the day you said (step # 4 he/she will tell you that they like you and maybe even engages or maybe kiss you. If you don't do it something will go wrong in about an hour Thursday
reply

You can also post test comments, but because the demonstrator uses straight PHP injection, rather than javascript, posting will reload the entire page. Note that any posts to the demonstrator section get deleted after a few hours. For normal comments, use the comment section at the bottom of this page =)

If I write a one, and then a zero, which number did I write?

Details

Nesting is automatic, and you can show it (or not) by using some CSS indenting. Custom styling for your own comments is also CSSable, so if you want to visually offset your own comments from everyone else's, you can.

In fact, there is quite a bit of styling that you can apply to the various elements, since essentially everything is either classed, or classless elements inside classed elements. All classes are prefixed with "EPC-" and certain elements in the post form have "EPC-..." id attributes, so you can hook into them with JavaScript, should you want to.

Every comment has its own anchor, and you can link to specific comments using them. For the PHP-generated code, hashes in the URL are not a problem, because the generated html already contains them. For the JavaScript-generated code, hashes in the URL are actually also just fine, because EasyPageComments.js will check for a URL hash, and keep it stored until you call the createCommentsList function, after which it'll tell the browser to jump to the specific comment indicated by the hash.

Email notification

EasyPageComments can send you an email every time someone posts a comment. This is enabled by setting the $notify variable to true, and filling in your email address as $to value. Note that even if you enable email notification, you will not receive emails for comments posted as yourself.

In additional to global notifications, EasyPageComments also lets people indicate whether or not they want to be notified by email whenever someone replies to their posts. This is done via a checkbox option in the comment posting form.

Getting the email #links right

NOTE: in order for the notification emails to contain the right comment #hash link, you must make sure that the $EPC_path variable points to your page. Thus, if your page is index.html, this variable should read:

$EPC_path = "index.html";

Owner posting by password

Because you know you're a trusted user, and because you don't want other people posing as you, filling in your nickname and email address and some comment that you would never write, posts by the owner are password protected. Rather than filling in your name and email address, plus answering the security question, you simply fill in your name, and the password you've set for your name in EasyPageComments.php:

// this is used to mark your own posts differently from everyone else's
var $admin_alias = "MyNickName";

// the owner nickname is password protected, which is used in place of an email address
var $admin_password = "This can be as long as you like; Unicode and case is respected.";

Even if you rely on PHP for your comment listing and post form, you will probably want to add EasyPageComments.js as on-page script, as its used to change the post form when the username happens to be yours. This is only a cosmetic change, but cosmetics are important on the web!

RSS

EasyPageComments will automatically set up RSS feeds for each comment thread you use, so you don't even have to worry about that. If you don't want this, you can turn off visibility for the "EPC-RSS-link" class, so the RSS link doesn't show, or you can turn RSS link generation off entirely by changing the EasyPageComments.php setting $rss = true; to $rss = false; instead.

Getting the RSS <link> URLs right

NOTE: in order for the RSS links to point to the correct webpage and #hash link, you must make sure that the $EPC_path variable points to your regular page. Thus, if your page is index.html, this variable should read:

$EPC_path = "index.html";

SQLite

Data is stored in SQLite databases, using SQLite3 format, with the following schema:

CREATE TABLE comments(id INTEGER PRIMARY KEY AUTOINCREMENT, page TEXT, name TEXT, email TEXT,
                      timestamp INTEGER, body TEXT, replyto INTEGER, notify INTEGER)

Thread topology uses the relation child.replytoparent.id and that's pretty much everything special about the layout. There is no separate users table, because that's something you would use user authentication for anyway, you don't overload a comment system with that.

If you need to manipulate the data, I recommend using SQLiteManager, which is an extension for FireFox. I know it's weird, but so far the best application for managing SQLite databases is a browser plugin. That said, it's a really good browser plugin (and ignore the nonsense comment about it crashing Thunderbird. Why you would try to install it for Thunderbird when it's a FireFox plugin, I have no idea) and you can use XULRunner to make it run stand-alone too, of course.

EasyPageComments creates one database file per 'page', so if you want to use multiple comment sections on a single page, the messages will be tracked using different databases, so that messages from one comment thread can't accidentally end up in another comment thread.

Customising EasyPageComments settings

If you want to customise the settings for EasyPageComments, simply open the EasyPageComments.php file and adjust the values at the start of the script. They are fairly self-explanatory:

// this is used to mark your own posts differently from everyone else's
var $admin_alias = "YourNameHere!";

// the owner nickname is password protected, which is used in place of an email address
var $admin_password = "Entire Unicode passphrases work!";

// what should be the security question for this page?
var $security_question = "If I write a three, and then a seven, which number did I write?";

// what are valid security answers for this page?
var $security_answers = array("37", "thirty seven", "thirty-seven", "thirtyseven", "37");

// should comment threads get an auto-generated RSS feed button?
// (if true, remember to also set the $EPC_path variable, below)
var $rss = true;

// should you be notified by email when someone posts a comment?
// (if true, remember to also set the $EPC_path variable, below)
var $notify = true;

// what's the email address to send those notifications to?
var $to = "test@example.org";

// what's the subject you'd like?
var $subject = "[EasyPageComments] page comment posted";

// where can the sqlite database be found
var $db_dir = "./sqlite";

// This variable should contain the name of your page. If your
// page is "myfunkypage.php", then this variable should be set
// to that. Relative locations such as "../index.html" are
// allowed.
//
// EPC_path is used for RSS feeds  elements as well as #hash
// links in email notifications, so if $rss and $notify are both
// set to "false", EPC_path will not be used, and its value is
// irrelevant.
var $EPC_path = "index.html";

Note that the $db_direntry simply says where you want your databases to reside. They don't need to exist yet, the script will make them if they don't exist yet, although the directory you want them to be in in has to exist. (The script won't make directories for you, only database files)

If you want to use the JavaScript approach, then you may want to put the .js and .php files in different directories. If this results in the JavaScript functions trying to call a .php file that isn't in the same directory as your page, you can modify the location the JavaScript should use for posting/getting the list by modifying the location in the EasyPageComments.js file:

EasyPageComments.EasyPageCommentLocation = "../moo/EasyPageComments.php";

Simply change this to the location of EasyPageComments.php relative to your page, and things should work just fine.

Using EasyPageComments with a user authentication system

If you have a user authentication system in place, you generally don't want the comment system to require your already-logged-in users to have to fill in their name and email address, and they're generally not required to fill in a security question, since they already logged in.

EasyPageComments lets you indicate that content is being generated for a trusted user by stating the user's name and email address before including EasyPageComments.php, using an associative array as follows:

// set the trusted user's name and email address
$EasyPageComments = array("name"  => "UserBot5000",
                          "email" => "bigbot@userbot.net");

// make EasyPageComments magic happen
require_once("EasyPageComments.php");

If you're using the JavaScript approach, you will probably want to use a passthrough file. Making one is relatively easy, so let's say we make a file called "EPC-passthrough.php", it will only need to have to following content:

<?php
  // session-based authentication handling code goes here
  require_once("user_authentication_script.php");
  $user = authenticate();

  // set the trusted user's name and email address
  $EasyPageComments = ($user->authenticated ? array("name"=>$user->name, "email"=>$user->email) : false);

  // make EasyPageComments magic happen
  require_once("EasyPageComments.php");
?>

This sets up trusted user content only if the user passed your authentication, generating the normal content otherwise. You will now also need to make the EasyPageComments.js script call this EPC-passthrough.php file instead of the normal EasyPageComments.php, so that user authentication can take place. This is almost trivially simple, only requiring you to tell JavaScript what the new file's location is:

// Set alternate EasyPageComments location
EasyPageComments.EasyPageCommentLocation = "EPC-passthrough.php";

// build comments list
EasyPageComments.createCommentsList('My Page Name');

// build comment post form
EasyPageComments.createCommentForm('My Page Name');

Comments

To show that one page can have multiple comment threads (but also because a demonstrator is not the "real" thing), there's also the actual comment thread for this page. If you have any questions or suggestions, do let me know by posting a comment!

Leave a comment

And please do NOT use this section for testing, this is the normal page comments section. It's for asking questions or leaving feedback. If you want to test, use the demonstrator thread instead (yes, that one is POST based)