Why multiple Disqus threads
When I met medium first time, I was shocked that this website looks not only so concise, but also beautiful. No ads, no confusing elements, just the articles. Many detailed design can be found there, including loading progress bar, inline comments, and menubar animation. I didn't know that medium was already famous engough, until I found @fat, one of the founders of Bootstrap, is working there. I deside to make my own version of medium in my blog. Animations are not difficult for me at all, so I started at the implementation inline comments.
This blog is hosted on Github pages, powered by Jekyll. It's a static site, so no backend supports here. Disqus provides comments by adding iframes to static pages. So adding multiple Disqus threads can be a solution for inline comments.
However, Disqus only allow one thread in a page, since it uses unique element
#disqus_thread as its container, and it uses global variables such as
disqus_identifier. No official solutions for multiple Disqus threads found, but somebody already solved this problem.
Existing solutions and problems
Mystrdat's article provides 2 possible ways:
- Using iframes to load Disqus threads
Disqus.Resetto switch between threads in one page
There are 3 main work to do:
- Give each passage an unique identifier
- Show / hide comments counts
- Show / hide Disqus threads
Give each passage an unique identifier
Disqus threads are identified by its disqus_identifier, so each passage should have a unique identifier. We can select all elements that considered as "passages", and simply use automatically increasing numeric index as identifier. This solution works, but when article are modified, for example a new passage are inserted to the head of article, all the following passage's identifier would move, comment threads will be assigned to wrong passages. There's no simple solution for this, but there is a easy way to lower the possibility that changes make old identifier invalid.
First, devide article into sections. Consider the identifier
section-2-3, which means "The 3rd passage of section 2", its identifier won't move while section 1, 2 or 4 have any changes. Since
<h1> is for page header, I can use
<h2> as divider of sections. We can devide sections to even smaller sections by
<h3>, and so on.
Second, use different identifier for different elements. The most commonly generated element in markdown is
<div class="highlight"> are also possible. For example, identifier
section-2-ol-3 means "3rd
<ol> element in section 2. This ensures that when other element changes,
<ol> elements' identifier are not effected.
Please tell me if there are better simple ways to deal with this problem.
Show / hide comments counts
From [guide] provided by Disqus, we can get comment counts by loading a script. This script will insert comment count string to certain elements. String of comment count can be configure in Disqus admin panel.
CSS 3 provides
:empty pseudo selector. we can these selector to style the count element. First we set string for zero comment to empty. In this way, count element with empty content can be selected by
:empty and then be styled as invisible.
Show / hide Disqus threads
This is the most difficult part. There are serveral steps to accomplish this.
- insert an
iframeand make Disqus to load correct comment thread in an inner iframe.
- adjust height of
iframewhen inner iframe's size changes
iframeinstead of destory it when user close thread, so we only need initialize
We should use source of
iframes that under ours control, so it can't be an cross site one. There are 3 choices.
- An special static HTML file exists in our jekell blog.
- base64 url
In the first way, we can include scripts in the special HTML file to communicate with the main page. But there are several shortcomings. First, it will cost at least one more http request to load a thread. The inner iframe's loading will be delayed. Second, this will force user to create an special file in thier blog instead of just change a theme.
The second way is better for that we saved a http request and that no special file is required. But IE doesn't support it.
From MSDN we know:
Data URIs are supported only for the following elements and/or attributes.
object (images only)
CSS declarations that accept a URL, such as background, backgroundImage, and so on.
So the second one is out. Let's discuss the third one. For both iframe with src of dataURL or
about:blank, the browser consider it as document in the same domain with main page. We can directly control its content by
document.write. See Eric Anderson's article
What we should do is to create an iframe with its
src set to
about:blank, and then write all its content, including info about thread to load:
var iframe = document.createElement('iframe') iframe.allowtransparency = true iframe.src = "about:blank" someNode.appendChild(iframe) iframe.contentWindow.document.open('text/html', 'replace') iframe.contentWindow.document.write(/* HTML code */) iframe.contentWindow.document.close()
The HTML code may looks like:
In this way, we are able to pass necessary arguments to
iframe, and make Disques to load correct thread in
I found an small lib for this: iframe-resizer
We should include the iframe part of the lib into our
iframe, and include main file into our main page, so that the height of our
iframe will be auto set to its content.
Show and hide
This is much simpler. just do it with jQuery.
Demo page and common lib
The first demo of this is my own blog. Try to add some inline comment in this page!
I haven't, but will write an jQuery lib for this. Wait for it or see code here now for help.