2005-09-19

Custom Blogger comments form (4): spam protection

After some problems with the regular expression I used to read cookies, I decided to do a little rewrite of the code. This cookie problem is fixed now. You'll find the new code below.

Spam protection was something I wanted to add. Too bad I didn't get it working on all my blogs in Internet Explorer (it worked fine in other browsers). I'll leave the code on this page and keep it embedded on my test blog for anyone who would like to test it. If anyone has ideas on how to get this working under Internet Explorer please let me now.

Note that you'll have to remove some lines if you want to use Blogger's spam protection and please read Blogger's help on spam protection first.

<form id="cFrm" action="http://www.blogger.com/login-comment.do" method="post">
<script type="text/javascript">
//<![CDATA[
  var expires = new Date();
  expires.setFullYear(expires.getFullYear()+1);
  function setCookie(name, value) {
    document.cookie = name +'='+ escape(value) +'; expires='+ expires.toGMTString();
  }
  function getCookie(name) {
    var key = name + '=';
    var c = document.cookie;
    var i = c.indexOf(key);
    if (i < 0) return '';
    var j = c.indexOf(';', i + key.length);
    if (j < 0) j = c.length;
    return unescape(c.substring(i + key.length, j));
  }
  function trim(text) {
    return text.replace(/^\s+|\s+$/g, '');
  }
  var bgPosted = false;
  function cFrmPost() {
    with (cFrm) {
      anonName.value = trim(anonName.value);
      anonURL.value  = trim(anonURL.value);
      postBody.value = trim(postBody.value);
      if (anonName.value == '') {
        alert('Please enter your name');
        anonName.focus();
        return false;
      }
      if (postBody.value == '') {
        alert('Please enter a comment');
        postBody.focus();
        return false;
      }
      anonURL.value = anonURL.value.replace(/^http:\/\//g, '');
    }
    bgPosted = true;
    return true;
  } 
  function bgpostLoad() {
    if (bgPosted == true) {
      if (cFrm.remember.checked) {
        setCookie('anonName', cFrm.anonName.value);
        setCookie('anonURL', cFrm.anonURL.value);
      }
      window.location.reload();
    }
  }
//]]>
</script>
<iframe style="position:absolute;left:-9999px;top:0" name="bgpost" onload="bgpostLoad()"></iframe>
<div>
  <input type="hidden" name="blogID" value="<$BlogID$>" />
  <input type="hidden" name="postID" value="<$BlogItemNumber$>" />
  <input type="hidden" name="isPopup" value="false" />
  <input type="hidden" name="iden" value="Other" />
</div>
<dl>
  <dt><label for="uname">Name</label></dt>
  <dd><input type="text" id="uname" name="anonName" maxlength="100" /></dd>
  <dt><label for="url">Homepage</label></dt>
  <dd><input type="text" id="url" name="anonURL" maxlength="100" /></dd>
<!-- START SPAM PROTECT remove comment to enable
  <dt><label for="captcha">Word verification</label></dt>
  <dd>
    <img src="http://www.blogger.com/captcha?postID=<$BlogItemNumber$>" height="70" width="200" alt="Verification image" />
    <br /><input type="text" id="captcha" name="captcha" /><br />
    This is <a href="http://help.blogger.com/bin/answer.py?answer=1203">spam protection</a>.
    Please enter the text in the image above to leave your comment.
  </dd>
END SPAM PROTECT remove comment to enable -->
  <dt><label for="comment-body">Comment</label></dt>
  <dd><textarea id="comment-body" name="postBody" cols="60" rows="10"></textarea>
<script type="text/javascript">
//<![CDATA[
  var cFrm = document.getElementById('cFrm');
  cFrm.target = 'bgpost';
  cFrm.onsubmit = function(){return cFrmPost()};
  if (document.cookie != '') {
    cFrm.anonName.value = getCookie('anonName');
    cFrm.anonURL.value = getCookie('anonURL');
  }
  cFrm.postBody.value = '';
  if (cFrm.captcha) cFrm.captcha.value = '';
  document.write(
    '</dd><dd><input type="checkbox" id="remember">'+
    ' <label for="remember">Remember me</label>'
  );
//]]>
</script>
  </dd>
</dl>
<p><input type="submit" name="post" value="Post" /></p>
</form>

How to use this code on your blog? It's simple. Search your template for </BlogItemComments>. After it you should paste the code. Now change the link to the comments. Your don't want it to point to the standard form.

<a href="<$BlogItemPermalinkUrl$>#comments">Comments (<$BlogItemCommentCount$>)</a>

You can also download an example of how to embed it in Douglas Bowman's Minima template.

44 comments:

Swipe said...

Hi. This is a great site. I've used this javascript on my blog and I like it.

If I may ask, would you be adding a functionality that automatically links blogger user?

Jasper said...

I might add that later. I'm not sure if it's possible, but I'll give it a look.

Swipe said...

Hi. me again. could this have some conflict with other javascripts? I asked a couple of friends to try posting comments but their comments don't end up on the page. I took out the script for the mean time.

thanks.

Jasper said...

I don't know what other Javascripts you are using. It might be the spam filter.. it depends too much on the load order of the iframe content and the verification image in the commenting form. I've deleted spam protection on my blog for now, it needs more testing :(

Swipe said...

ok. thanks. will check in once in a while to see what other goodies you have for us who are not so adept at HTML and Javascript.

Kapil said...

Does it mean I can actually disable the haloscan comments and use only blogger for non-registered users also?

Jasper said...

It's up to you whether to disable Haloscan

oky said...

it's cool jasper.

but in other encodings, for example turkish (8859-9), the turkish characters are being displayed as "?" in firefox. in universal encoding (UTF-8) it is ok but when i change my blog to universal encoding, the turkish characters that i have posted 'till now are being displayed as "?" in firefox :)

do you have any idea for me to solve this problem?
if not, don't woorry hehe ;)

wongpk said...

Hm.. This is very nice, thank you... But then, how to enable the spam protection?

Richard said...

Thanks for the great hack.

Just one problem: the labels ("name", "homepage", "comment") get displaced upwards by the new Blogger backlinks feature. See here for an example. If you expand the backlinks (click on the triangle), it gets even worse: the form labels end up overlapping with comment text, several inches above the forms!

Any idea how to fix this?

Jasper said...

The problem is caused by the absolute positioning of the definition titles. Left floating them in the left margin of the definition data should solve it. I'll post an example in a new post.

G said...

hi, thanks for this cool script.
i have the same problem as "oky" up there, swedish characters display as questionmarks.
any solution yet?

/ G

Jasper said...

Just use UTF-8 character encoding on your blog. I have a Dutch blog where é and ë characters are used.. no problem when I'm using UTF-8.

Stephen said...

Thanks for posting the example--my template is a patchwork quilt and it didn't work until I checked the example. ;)

Johan Sundström said...

There is serious magic going on behind the scenes when you post comments to Blogger; I just peered at what goes on net traffic wise (via LiveHTTPHeaders) when Firefox posts one of these, and they certainly don't take the easy route in getting the comment to the server, the guess to the CAPTCHA to that server and the OK you're done result back to the client. I'm surprised this works across many browsers, though I presume it's all according to the HTTP standard, more or less.

Next step ought to be installing ethereal, saving a complete successful Firefox comment post and a complete failed IE post and comparing what comes out differently. Or is it the javascript errors your page triggers for IE that you can't find out any specifics on?

Johan Sundström said...

But after trying out this with IE6 I don't understand which problems you are trying to solve; it works well enough posting with CAPTCHA protection under IE6 too; there are just some visual misfeatures with the textarea and some javascript error message you trig somehow. Is that the source of your troubles?

Johan Sundström said...

Okay, now I have played around with this a bit on my own test page. There are plenty of error sources that could pop up and request further user interaction from the user before letting a post through on the result page we hide in the bgpost IFRAME. In these cases, we can't just assume that all went fine and proceed with reloading the post page, hoping it has got the new comment.

Since the post page is loaded from www.blogger.com, we can't peek at it to see whether things went fine or what went wrong. What we can do, however, is peek back at post page after posting, by loading it in the background from the iframe onload hook, and checking its xmlhttprequest.responseText to see whether the comment we just wrote actually make it through. In that case, we can go on just reloading the page as presently, and be sure that it worked. If it failed, we can change the target of the form to _self, and resubmit it, letting the user rectify her mistakes on the standard Blogger page.

It's very backwards, but in a javascript only environment this is probably as good as it gets without any backend support from Blogger.

Also worth noting is that when testing whether the comment we posted ended up on the post page or not, we can't just test for responseText.indexOf( textarea.value ), since Blogger (for instance) makes <a> tags uppercase, gives them a rel=nofollow attribute and so on, so we need some normalization of both the textarea contents and the responseText (.replace(/<[^>]*>|\n/g, '') for instance), or settling for a more basic approach, perhaps just counting the comments on the page we are at now and the page we fetch.

Or give up, all together. ;-)

Jasper said...

Thanks for the effort! It is appreciated!

charles said...

The script is really helpful

ted said...

this comment thing is really unique

dreamflow said...

Is it at all possible to use img tags without resorting to edit comments?

ecmanaut stated in his post:
"each comment on your Blogger blog is technically a blog post."

Is there a way to automatically put images on comments?

Jasper said...

@dreamflow: I don't know what you had in mind regarding the images. You could use CSS to place background images.

dreamflow said...

thanks jasper for that quick reply.

I am currently developing (or should we say collecting) blogger comments form hack). I am hoping to release it soon as livecomment.

so far my blogspot livecomment form includes:
1. your comment form.
2. singpolyma's automatic sign-in for blogger users.
2. scriptygoddes's live preview
3. alexking's quicktag
4. dkgoodman's photo favatar

Now the only missing piece of livecomment before release is a smiley pack and CAPTCHa for ie6.

I have included the smiley pack already (I made it as an image background button in alexking's quicktag. My problem is how to automatically generate images inside the comment area, so that when you click the smiley it will show inside the comment, instead of just text.

Right now when I click on [ ; ) ] for example, ; ) text will show instead of an image of the animated wink. So if you know a script to generate an img tag inside, I would really apreciate it. You mentioned a css background work around.

Johan Sundström stated that CAPTCHA is working for ie6, but explained no further, so if he is reading this, it would be helpful if he showed how.

Thanks again Jasper, I was amaze at your quick reply.

dreamflow said...

I got it! The solution to CAPTCHA to work for IE6 seems to be this:


1. label for="f-captcha"
2. id="f-captcha"


Now, if only I could get the code of ecmanaut for his comment author highlighting.

Also, if you be so kind as to show how a smiley can work in your form.

Hope that helps.

Jasper said...

@dreamflow: you might want to use JavaScript to convert text smileys to images. I guess you can find working code using Google.

dreamflow said...

Jasper,

I've already tried doing that. I've ported scriptygoddess smiley's pack to alexking's quicktag's. Instead of text, an img tag on your form will automatically show.

the problem is that img tags are not accepted, and will render the comment to be unacceptable and blank. So I am back to square one.

If you know a better script, I would appreciat it.

Jasper said...

@dreamflow: You need use the script to convert text smileys in the comments on your page (after the comment has been made and is present on the server). Blogger doesn't accept images in it's server side script, so you can't do anything about that on the client side. You can't use images in a comment (as you have found out yourself).

dreamflow said...

what script is allows that?
Right now, there is only one option available, that I know of, and that is your edit options script.

If you can point me out to the exact location of the script that automatically do this, without resorting to manual editing, that would be super.

Thanks again Jasper.

Jasper said...

@dreamflow: I don't know an exact location of a script that automatically solves your problems. Try looking for it on Google. I'm sure that there will be some scripts ready to use out there.

Maggi said...

Hi, thans fr this hack. There is one thing though, same problem as oky. When I type Icelandic letters (Þ, Æ, Í, É) they appear as "?", but then i tryed UTF-8 and then it just came out like this: ������. I use Western (Windows-1252), acn you please help me?
You can see it here:
www.prufun.blogspot.com.

In advance, thanks.

Jasper said...

@Maggi: seen answer in comments above.

Maggi said...

Yeah, but that didn't work. I tryed UTF-8 but it became scrambled, ������. When I use Western (Windows-1252) it appears as a questionmark.

James said...

How can I adjust the width of the comment box? I'd like to make it thinner.

James said...

Nevermind, figured it out.

kevin said...

nice job, thank you.

Dr Haisook said...

Hi Jasper,

I've installed your comment form successfully in my blog and it's working like a charm. Thank you. But I wonder how can I get the form boxes to be aligned more to the left? I mean to be in line with the items above and below.

Take a look:
http://dr-haisook.blogspot.com/2006/03/testing-comment-system.html

I'd appreciate your response, for I'm very novice when it comes to coding.

Jasper said...

@Dr Haisook: You can use the CSS example from my post on semantic forms.

Anonymous said...

I'm sure it's a no-brainer for you scripters, but how do I make the commenter's name link to his url?
Thanks

yash gupta said...

hi, I read the comments and am unsure of the status of "custom smileys in comments" does this code currently support custom smileys? if not, when can I expect to get a version with smiley featre? I`d really like to use this asap.
thanks again for this. Great job!

Goldmen said...

I had been using this hack without a problem for months but now it the verification image is not being displayed. Any ideas?

audienceone said...

It appears that blogger has updated their method on generating the visual captcha. Instead of the old

http://www.blogger.com/captcha?postID=<$BlogItemNumber$>

the new visual captcha generation url is now

http://www.blogger.com/captcha?type=IMAGE&captchaKey=SOME_CAPTCHA_KEY GOES_HERE

and obviously the audio captcha is

http://www.blogger.com/captcha?type=AUDIO&captchaKey=SOME_CAPTCHA_KEY GOES_HERE

I've tried appending <$BlogItemNumber$> to the new code but wouldn't work. The new captchaKey is alphanumeric whereas BlogItemNumber is only numeric.

I'm digging for some fixes, but none is available yet. I hope jasper has a solution.

Here's a link to a possible fix: http://forum.iopus.com/viewtopic.php?t=817

Retokado said...

have a problem with my comment form.

Everytime someone posts a comment it get posted on the latest blog post, not on the post he/she intended to comment on.

Whats the prob? Need help.
http://pinoydreamacad.blogspot.com/

Jesse said...

Does this still work

amonereb said...

I'm not sure it does... at least I cannot get it to work. When user posts comment the server returns a page not found error...

Anyone got an update/alternative?