Disqus Integration with Ember
Update - now here is Ember Addon .
I just finished integrating async Disqus into ember blogging frameworks ( see source here ), and here is how I did it:
First set the parameters as objects (easily accessible for all components):
App.DisqusOptions = Em.Object.create({ shortname: 'example',
Then download disqus once and only once using the code that they give you. I did this in the component:
App.DisqusCommentsComponent = Em.Component.extend({ setupDisqus: function() { if (!window.DISQUS) { var disqusShortname = App.DisqusOptions.get('shortname'); window.disqus_shortname = disqusShortname; // Mimic behaviour as if we're setting variable in a script tag var dsq = document.createElement('script'); dsq.type = 'text/javascript'; dsq.async = true; dsq.src = '//' + disqusShortname + '.disqus.com/embed.js'; (document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(dsq); } }.on('didInsertElement'), });
You can also do this by setting the disqusLoaded property of the options property to true after running the setupDisqus() method and checking for it.
In addition, you can do this in your application template using script tags, but this will result in an error if you load the script on a page that does not exist, and an element with id #disqus_thread .
Then use Em.View or Em.Component , which you place on every page where you want comments to be displayed. Let me call it App.DisqusCommentsComponent . This component will not have a layout (template). Since this component will load every time we change routes / messages, this is an ideal place to call DISQUS.reset() .
App.DisqusCommentsComponent = Em.Component.extend({ elementId: 'disqus_thread', // ID is used by Disqus to know where to load the comments timer: null, setupDisqus: function() { // setupDisqus() code left out for purposes of not repeating myself }.on('didInsertElement'), loadNewPostComments: function() { if (window.DISQUS) { this.reset(); } else { // If DISQUS hasn't finished async loading yet, check again in 100 ms. Once it loaded, the above this.reset() will be called. this.set('timer', Em.run.debounce(this, this.loadNewPostComments, 100)); } }, reset: function() { var controller = this.get('parentView.controller'); var postIdentifier = controller.get('urlString'); var postUrl = window.location.href; // Since this view has the elementId Disqus targets, we need to wait until after the view has finished rendering to call the reset function, which searches for #disqus_thread Em.run.scheduleOnce('afterRender', function() { window.DISQUS.reset({ reload: true, config: function () { this.page.identifier = postIdentifier; this.page.url = postUrl; } }); }); }, });
NB The postIdentifier variable is the set of properties on the controller for each blog post that is downloaded as the controller model. You will need a similar way to identify each route to track comments.
Et voila! Your asynchronous call will be executed every time a user changes routes to one that has a comment component in its template. For instance:
JS Disk Configuration Variables
Whenever you set a configuration variable, such as these , you need to set their property in the window. For instance:
var disqusShortname = App.DisqusOptions.get('shortname'); window.disqus_shortname = disqusShortname;
Sidenote: Number of Comments
If you want to use the Disqus comment count function, you can take a similar approach to the above. However, you will also need to re-open the {{link-to}} sub-call view using the following:
Em.LinkView.reopen({ addDisqusTag: function() { var commentCount = this.get('commentCount'); if (commentCount) { var isLinkToPost = this.get('isLinkToPost'); var href = this.get('href'); var disqusTag = '#disqus_thread'; this.set('href', href + disqusTag); } }.on('willInsertElement'), });
Now, if you do the following in your template, it will return commentCount:
{{
Hope this helps. Let me know if you have any questions!