I am a big fan of blogCFC and like everyone else after an install I like to make a few customizations. I recently upgraded the look and feel to my website and have to say I am pretty happy with the way everything turned out. One of the new additions is inline comments. BlogCFC by default has an add comment link that opens up a new window for users to add comments. While this works perfectly fine and there is nothing wrong with this, I wanted the ability for users to leave comments without leaving the page. In this tutorial I am going to run through what I needed to do to get this to work.

The first thing you need to do is open the addComment template located in the blog root and remove the following lines.

view plain print about
1<cfset closeMe = false>
2<cfif not isDefined("url.id")>
3 <cfset closeMe = true>
4<cfelse>
5 <cftry>
6 <cfset entry = application.blog.getEntry(url.id,true)>
7 <cfcatch>
8 <cfset closeMe = true>
9 </cfcatch>
10 </cftry>
11</cfif>
12<cfif closeMe>
13 <cfoutput>
14 <script>
15 window.close();
16 </script>
17 </cfoutput>
18 <cfabort>
19</cfif>
You are going to replace that code with the following. All this code is doing is making sure that we are able to get the details for this entry. If we can not than set our showForm variable to false which we will use in a minute to wrap our form with.
view plain print about
1<cfset showForm = true>
2<cftry>
3 <cfset entry = application.blog.getEntry(articles.id,true)>
4 <cfcatch>
5 <cfset showForm = false>
6 </cfcatch>
7</cftry>
Next we are going to wrap the entire form with the following code. The entry information is required if we are going to show the add comment form.
view plain print about
1<cfif showForm>
2 <cfif isDefined("form.addcomment") and entry.allowcomments>
3 ...
4 </cfif>
5<cfelse>
6 comments disabled for the moment.
7</cfif>

Now that we are showing the comment form inline we need to make some changes. The first change is to take away the post title since we are on that post already. Simply remove the following line

view plain print about
1<div class="date">#rb("comments")#: #entry.title#</div>
Some of this is cosmetic but I will share it with you anyways. Next I am going to wrap the entire form in a div, change the form action handler & clean up the form.
view plain print about
1<div id="comment-form">
2    <form action="#application.blog.makeLink(entry.id)#" method="post">
3    <input type="hidden" name="entryId" value="#entry.id#">
4    <p>
5        <label for="name">#rb("name")#: <strong>*</strong></label><br />
6        <input type="text" id="name" name="name" value="#form.name#" class="text">
7    </p>
8    <p>
9        <label for="email">#rb("emailaddress")#: <strong>*</strong></label><br />
10        <input type="text" id="email" name="email" value="#form.email#" class="text">
11    </p>
12    <p>
13        <label for="website">#rb("website")#: </label><br />
14        <input type="text" id="website" name="website" value="#form.website#" class="text">
15    </p>
16    <p>
17        <label for="comments">#rb("comments")#: <strong>*</strong></label><br />
18        <textarea name="comments" id="comments" class="textarea">#form.comments#</textarea>
19    </p>
20    <cfif application.useCaptcha>
21 <p>
22        <cfset variables.captcha = application.captcha.createHashReference() />
23        <input type="hidden" name="captchaHash" value="#variables.captcha.hash#" />
24        <label for="captchaText" class="longLabel">#rb("captchatext")#:</label><br/>
25        <input type="text" name="captchaText" size="6" class="captcha"/><br>
26        <img src="#application.blog.getRootURL()#showCaptcha.cfm?hashReference=#variables.captcha.hash#" vspace="5"/>
27     </p>
28    </cfif>
29     <p class="bg">
30        <input type="checkbox" class="checkBox" id="rememberMe" name="rememberMe" value="1" <cfif isBoolean(form.rememberMe) and form.rememberMe>checked</cfif>>
31        <label for="rememberMe" class="longLabel">#rb("remembermyinfo")#</label>
32     </p>
33     <p class="bg">
34        <input type="checkbox" class="checkBox" id="subscribe" name="subscribe" value="1" <cfif isBoolean(form.subscribe) and form.subscribe>checked</cfif>>
35        <label for="subscribe" class="longLabel">#rb("subscribe")#</label>
36     </p>
37        <p style="clear:both">#rb("subscribetext")#</p>
38     <p style="text-align:center">
39        <input type="reset" id="reset" value="#rb("cancel")#" onClick="if(confirm('#rb("cancelconfirm")#')) { window.close(); } else { return false; }"> <input type="submit" id="submit" name="addcomment" value="#rb("post")#">
40 </p>
41    </form>
42    </div>

Add the following line so when the form is submitted we can pass the entryId

view plain print about
1<input type="hidden" name="entryId" value="#entry.id#">
And then in the area that handles the form submission change any value of url.id > form.entryId

The next change is to Remove the following code. This code would reload the opening page and close the window when it was a popup. We just want to relocate to the same entry so the comments are refreshed.

view plain print about
1<!--- reload page and close this up --->
2 <cfoutput>
3 <script>
4 window.opener.location.reload();
5 window.close();
6 </script>
7 </cfoutput>
8 <cfabort>
And change it to this
view plain print about
1<!--- redirect --->
2<cflocation url="#application.blog.makeLink(form.entryid)#" addtoken="false">
3<cfabort>
Finally we have to make a change the anchor link. This is so that when users click on comments from the main page they are taken directly to the comments without having to read the entry. Change the named anchor link for the comments hyperlink in the entry footer (index.cfm) from #comments
to #comments-begin
And add a named anchor to the begining of the comments section. If you do not do this the link will take you to the comments box on the form instead of the top of the comments.

I know this is a lot of rabmling and this is mostly due to the fact that I jotted notes down as I was doing it last weekend. Below is my final code in my addComment.cfm template. If you have any questions feel free to ask.

view plain print about
1<cfprocessingdirective pageencoding="utf-8">
2<!---
3    Name : addcomment.cfm
4    Author : Raymond Camden
5    Created : February 11, 2003
6    Last Updated : April 13, 2007
7    History : Reset history for version 5.0
8                 : Lengths allowed for name/email were 100, needed to be 50
9                 : Cancel confirmation (rkc 8/1/06)
10                 : rb use (rkc 8/20/06)
11                 : Scott updates the design a bit (ss 8/24/06)
12                 : Default form.captchaText (rkc 10/21/06)
13                 : Don't log the getentry (rkc 2/28/07)
14                 : Don't mail if moderating (rkc 4/13/07)
15    Purpose         : Adds comments
16--->

17
18<cfif not isDefined("form.addcomment")>
19    <cfif isDefined("cookie.blog_name")>
20        <cfset form.name = cookie.blog_name>
21        <cfset form.rememberMe = true>
22    </cfif>
23    <cfif isDefined("cookie.blog_email")>
24        <cfset form.email = cookie.blog_email>
25        <cfset form.rememberMe = true>
26    </cfif>
27    <!--- RBB 11/02/2005: Added new website check --->
28    <cfif isDefined("cookie.blog_website")>
29        <cfset form.website = cookie.blog_website>
30        <cfset form.rememberMe = true>
31    </cfif>    
32</cfif>
33
34<cfparam name="form.name" default="">
35<cfparam name="form.email" default="">
36<!--- RBB 11/02/2005: Added new website parameter --->
37<cfparam name="form.website" default="">
38<cfparam name="form.comments" default="">
39<cfparam name="form.rememberMe" default="false">
40<cfparam name="form.subscribe" default="false">
41<cfparam name="form.captchaText" default="">
42
43<cfset showForm = true>
44<cftry>
45    <cfset entry = application.blog.getEntry(articles.id,true)>
46    <cfcatch>
47        <cfset showForm = false>
48    </cfcatch>
49</cftry>
50
51<cfif showForm>
52<cfif isDefined("form.addcomment") and entry.allowcomments>
53    <cfset form.name = trim(form.name)>
54    <cfset form.email = trim(form.email)>
55    <!--- RBB 11/02/2005: Added new website option --->
56    <cfset form.website = trim(form.website)>
57    <cfset form.comments = trim(form.comments)>
58
59    <cfset errorStr = "">
60
61    <cfif not len(form.name)>
62        <cfset errorStr = errorStr & rb("mustincludename") & "<br>">

63    </cfif>
64    <cfif not len(form.email) or not isEmail(form.email)>
65        <cfset errorStr = errorStr & rb("mustincludeemail") & "<br>">
66    </cfif>
67    <cfif len(form.website) and not isURL(form.website)>
68        <cfset errorStr = errorStr & rb("invalidurl") & "<br>">
69    </cfif>
70    
71    <cfif not len(form.comments)>
72        <cfset errorStr = errorStr & rb("mustincludecomments") & "<br>">
73    </cfif>
74    
75    <!--- captcha validation --->
76    <cfif application.useCaptcha>
77        <cfif not len(form.captchaText)>
78         <cfset errorStr = errorStr & "Please enter the Captcha text.<br>">
79        <cfelseif NOT application.captcha.validateCaptcha(form.captchaHash,form.captchaText)>
80         <cfset errorStr = errorStr & "The captcha text you have entered is incorrect.<br>">
81        </cfif>
82    </cfif>
83        
84    <cfif not len(errorStr)>
85     <!--- RBB 11/02/2005: added website to commentID --->
86         <cftry>            
87             <cfset commentID = application.blog.addComment(form.entryid,left(form.name,50), left(form.email,50), left(form.website,255), form.comments, form.subscribe)>
88            <!--- Form a message about the comment --->
89            <cfset subject = rb("commentaddedtoblog") & ": " & application.blog.getProperty("blogTitle") & " / " & rb("entry") & ": " & entry.title>
90            <cfsavecontent variable="email">
91            <cfoutput>
92#rb("commentaddedtoblogentry")#:    #entry.title#
93#rb("commentadded")#:         #application.localeUtils.dateLocaleFormat(now())# / #application.localeUtils.timeLocaleFormat(now())#
94#rb("commentmadeby")#:         #form.name# <cfif len(form.website)>(#form.website#)</cfif>
95#rb("ipofposter")#:            #cgi.REMOTE_ADDR#
96URL: #application.blog.makeLink(form.entryId)###c#commentID#
97
98    
99#form.comments#
100    
101------------------------------------------------------------
102#rb("unsubscribe")#: %unsubscribe%
103This blog powered by BlogCFC #application.blog.getVersion()#
104Created by Raymond Camden (ray@camdenfamily.com)
105            </cfoutput>
106            </cfsavecontent>
107    
108            <cfif not application.commentmoderation>
109                <cfset application.blog.notifyEntry(form.entryid, trim(email), subject, form.email)>
110            <cfelse>
111                <cfset application.blog.notifyEntry(form.entryid, trim(email), subject, form.email, true)>
112            </cfif>
113                    
114            <cfcatch>
115                <cfif cfcatch.message is not "Comment blocked for spam.">
116                    <cfrethrow>
117                </cfif>
118            </cfcatch>
119            
120        </cftry>
121                
122        <cfmodule template="tags/scopecache.cfm" scope="application" clearall="true">
123        <cfset comments = application.blog.getComments(form.entryid)>
124        <!--- clear form data --->
125        <cfif form.rememberMe>
126            <cfcookie name="blog_name" value="#trim(htmlEditFormat(form.name))#" expires="never">
127            <cfcookie name="blog_email" value="#trim(htmlEditFormat(form.email))#" expires="never">
128         <!--- RBB 11/02/2005: Added new website cookie --->
129            <cfcookie name="blog_website" value="#trim(htmlEditFormat(form.website))#" expires="never">
130        <cfelse>
131            <cfcookie name="blog_name" expires="now">
132            <cfcookie name="blog_email" expires="now">
133            <!--- RBB 11/02/2005: Added new website form var --->
134            <cfset form.name = "">
135            <cfset form.email = "">
136            <cfset form.website = "">
137        </cfif>
138        <cfset form.comments = "">
139        
140        <!--- redirect --->
141        <cflocation url="#application.blog.makeLink(form.entryid)#" addtoken="false">
142        <cfabort>
143        
144    </cfif>    
145</cfif>
146
147<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" />
148
149<html>
150<head>
151    <cfoutput><title>#application.blog.getProperty("blogTitle")# : #rb("addcomments")#</title></cfoutput>
152    <link rel="stylesheet" href="includes/style.css" type="text/css"/>
153    <meta content="text/html; charset=UTF-8" http-equiv="content-type">
154</head>
155
156<body id="popUpFormBody">
157
158<cfoutput>
159
160<div class="body">
161</cfoutput>
162
163<cfif entry.allowcomments>
164    <br><br>
165    <img src="http://www.danvega.org/blog/images/postcomments.gif">    
166    <cfif isDefined("errorStr") and len(errorStr)>
167        <cfoutput><b>#rb("correctissues")#:</b><ul style="color:red;">#errorStr#</ul></cfoutput>
168    </cfif>
169    <cfoutput>
170    <div id="comment-form">
171    <form action="#application.blog.makeLink(entry.id)#" method="post">
172    <input type="hidden" name="entryId" value="#entry.id#">
173    <p>
174        <label for="name">#rb("name")#: <strong>*</strong></label><br />
175        <input type="text" id="name" name="name" value="#form.name#" class="text">
176    </p>
177    <p>
178        <label for="email">#rb("emailaddress")#: <strong>*</strong></label><br />
179        <input type="text" id="email" name="email" value="#form.email#" class="text">
180    </p>
181    <p>
182        <label for="website">#rb("website")#: </label><br />
183        <input type="text" id="website" name="website" value="#form.website#" class="text">
184    </p>
185    <p>
186        <label for="comments">#rb("comments")#: <strong>*</strong></label><br />
187        <textarea name="comments" id="comments" class="textarea">#form.comments#</textarea>
188    </p>
189    <cfif application.useCaptcha>
190 <p>
191        <cfset variables.captcha = application.captcha.createHashReference() />
192        <input type="hidden" name="captchaHash" value="#variables.captcha.hash#" />
193        <label for="captchaText" class="longLabel">#rb("captchatext")#:</label><br/>
194        <input type="text" name="captchaText" size="6" class="captcha"/><br>
195        <img src="#application.blog.getRootURL()#showCaptcha.cfm?hashReference=#variables.captcha.hash#" vspace="5"/>
196     </p>
197    </cfif>
198     <p class="bg">
199        <input type="checkbox" class="checkBox" id="rememberMe" name="rememberMe" value="1" <cfif isBoolean(form.rememberMe) and form.rememberMe>checked</cfif>>
200        <label for="rememberMe" class="longLabel">#rb("remembermyinfo")#</label>
201     </p>
202     <p class="bg">
203        <input type="checkbox" class="checkBox" id="subscribe" name="subscribe" value="1" <cfif isBoolean(form.subscribe) and form.subscribe>checked</cfif>>
204        <label for="subscribe" class="longLabel">#rb("subscribe")#</label>
205     </p>
206        <p style="clear:both">#rb("subscribetext")#</p>
207     <p style="text-align:center">
208        <input type="reset" id="reset" value="#rb("cancel")#" onClick="if(confirm('#rb("cancelconfirm")#')) { window.close(); } else { return false; }"> <input type="submit" id="submit" name="addcomment" value="#rb("post")#">
209 </p>
210    </form>
211    </div>
212    </cfoutput>
213    
214<cfelse>
215
216    <cfoutput>
217    <p>#rb("commentsnotallowed")#</p>
218    </cfoutput>
219    
220</cfif>
221</div>
222<cfelse>
223    unable to show comment entry form
224</cfif>
225
226</body>
227</html>


form style
view plain print about
1/* comments from users */    
2#comment-form {
3    margin-top:25px;
4    padding:10px;
5    background: #242424;
6    color:#f3f3f3;
7    font-family: Arial, Helvetica, sans-serif;
8    font-size:12px;
9    font-weight:bold;
10}
11
12#comment-form p {
13    margin-bottom: 15px;
14}
15#comment-form label {
16
17}
18#comment-form .text {
19    border:1px solid #f3f3f3;
20    width: 320px;
21    margin-top: 2px;
22    margin-right: 0pt;
23    margin-bottom: 2px;
24    margin-left: 0pt;
25    padding-top: 2px;
26    padding-right: 2px;
27    padding-bottom: 2px;
28    padding-left: 2px;
29}
30#comment-form .captcha {
31    border:1px solid #f3f3f3;
32    width: 245px;
33    margin-top: 2px;
34    margin-right: 0pt;
35    margin-bottom: 2px;
36    margin-left: 0pt;
37    padding-top: 2px;
38    padding-right: 2px;
39    padding-bottom: 2px;
40    padding-left: 2px;
41}    
42#comment-form .textarea {
43    width:320px;
44    height:125px;
45    font-family: Arial, Helvetica, sans-serif;
46    font-size:12px;
47}
48#comment-form .bg {
49    background-color: #999999;
50    padding-top: 3px;
51    padding-right: 3px;
52    padding-bottom: 3px;
53    padding-left: 3px;
54    width: 320px;
55}