Mappa Via Marconi 20, Bussolengo (VR)
Email info@devinterface.com

How to insert more Disqus comments box in a single page

Hello everyone!

For those not familiar Disqus is a platform that allows you to easily insert a box for comments on any website and allows users to use the their Facebook or Twitter account (but not only) to authenticate.

The limit of Disqus is that it associates any thread of comments to a unique url.
Consequently, it will expect that in every page there is only a comment box.

In most cases this limit is acceptable, but for some applications it is useful to put more comments boxes on a single page. As an example think about a blog where you want to give the opportunity to comment on each post directly from the main page which lists all the posts one under each other.

What I want to show you today is a method to overcome the limit of Disqus and easily implement a page with more comments boxes, as in the blog example.
Using an iframe and jQuery we will make the boxes also dynamically loaded.

Suppose that we have our page index.html.haml as follows and to already have a Disqus account:

1
2
3
4

- @posts.each do |post|
= show_for post do |s|
= s.attribute :title
= s.attribute :body

The idea is to create an iframe dynamically below each post and have it displayed / hidden by jQuery when you click on a link “comments”.

We start creating the page comments.html.haml that we want to load inside the iframe.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30

#disqus_thread

%noscript
Please enable JavaScript to view the
%a{:href => "http://disqus.com/?ref_noscript"} comments powered by Disqus.

%a.dsq-brlink{:href => "http://disqus.com"}
blog comments powered by
%span.logo-disqus Disqus


:javascript
var disqus_shortname = 'devinterface-example';

(function() {
var dsq = document.createElement('script'); dsq.type = 'text/javascript'; dsq.async = true;
dsq.src = 'http://' + disqus_shortname + '.disqus.com/embed.js';
(document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(dsq);
})();

function disqus_config() {
this.callbacks.onReady = [function() {
var frameHeight = $(document).height();
$('iframe.comment_frame', top.document).attr("height", frameHeight)
}];
this.callbacks.onNewComment = [function() {
var frameHeight = $(document).height();
$('iframe.comment_frame', top.document).attr("height", frameHeight)
}];
}

On this page, we insert the html and javascript provided by Disqus and we set the variable disqus_shortname.
Then, using the disqus_config function we set two callbacks for Disqus so that after the complete loading or aftere a new comment is inserted, the iframe that contains this page be appropriately resized
NOTE: resizing iframe “container” is only possible because the two page “index” and “comments” are on the same domain. If not, in fact, access to the parent of an iframe would be impossible for the security policy of browsers.

Now that we have created our comments page, we have only to add the iframe dynamically to the index page.
To make things more “cool” we use the count of comments for each post as the link that will open/close the comments box.

Now we return to the index page and modify it as follows:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34

- @posts.each do |post|
= show_for post do |s|
= s.attribute :title
= s.attribute :body
/ disqus comments
= link_to "", "/#{post.slug}/comments#disqus_thread", :class=> "dq_comment", :id => post.id
.comment_box{:id => "comment_#{post.id}"}

:javascript
var disqus_shortname = 'devinterface-example';

(function () {
var s = document.createElement('script'); s.async = true;
s.type = 'text/javascript';
s.src = 'http://' + disqus_shortname + '.disqus.com/count.js';
(document.getElementsByTagName('HEAD')[0] || document.getElementsByTagName('BODY')[0]).appendChild(s);
}());

$(document).ready(function(){
$(".dq_comment").click(function(e){
e.preventDefault();

var id = $(this).attr("id");
var href = $(this).attr("href");
var src = href.substring(0,href.length-14); // Remove #disqus_thread

if ($("#comment_"+id).is(':visible'))
$("#comment_"+id).html('');
else
$("#comment_"+id).append('<iframe scrolling="no" frameborder="0" src="'+src+'" class="comment_frame"></iframe>');

$("#comment_"+id).toggle('slow');
})
});

As you can see we have added the link with the unique url of the post and the tag # disqus_thread to activate the counter of the comments, as explained in the documentation.
Finally, using the jQuery function we intercepted the click on the link in such a way to dynamically create an iframe below the post with the url of our comments.html.haml page.
Obviously the comments page’s url have to be appropriately defined in our routes file.

Now you just need to open your browser and see your posts, each with its comments box dynamically loaded by clicking on the counter link.

NOTE: If you try these scripts on localhost, remember to add to the two Disqus javascript:

1

var disqus_developer = 1;

just below disqus_shortname.