Merge pull request #452 from Rocket1184/fetaure/client-async-comment-load

Async comment loading for dynamic websites
This commit is contained in:
Benoît Latinier 2018-07-27 13:30:27 +02:00 committed by GitHub
commit c801d18bd9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 73 additions and 19 deletions

View File

@ -95,5 +95,8 @@ In chronological order:
* Steffen Prince @sprin * Steffen Prince @sprin
* Upgrade to Misaka 2 * Upgrade to Misaka 2
* Rocka <i@rocka.me>
* Implementation and documentation about async comment loading
* [Your name or handle] <[email or website]> * [Your name or handle] <[email or website]>
* [Brief summary of your changes] * [Brief summary of your changes]

View File

@ -23,3 +23,34 @@ Now, either include `count.min.js` if you want to show only the comment count
You can have as many comments counters as you want in a page, and they will be You can have as many comments counters as you want in a page, and they will be
merged into a single `GET` request. merged into a single `GET` request.
Asynchronous comments loading
-----------------------------
Isso will automatically fetch comments after `DOMContentLoaded` event. However
in the case where your website is creating content dynamically (eg. via ajax),
you need to re-fetch comment thread manually. Here is how you can re-fetch the
comment thread:
.. code-block:: js
window.Isso.fetchComments()
It will delete all comments under the thread but not the PostBox, fetch
comments with `data-isso-id` attribute of the element `section#isso-thread` (if
that attribute does not exist, fallback to `window.location.pathname`), then
fill comments into the thread. In other words, you should change `data-isso-id`
attribute of the element `section#isso-thread` (or modify the pathname with
`location.pushState`) before you can get new comments. And the thread element
itself should *NOT* be touched or removed.
If you removed the `section#isso-thread` element, just create another element
with same TagName and ID in which you wish comments to be placed, then call the
`init` method of `Isso`:
.. code-block:: js
window.Isso.init()
Then Isso will initialize the comment section and fetch comments, as if the page
was loaded.

View File

@ -3,7 +3,7 @@ define(["app/lib/promise", "app/globals"], function(Q, globals) {
"use strict"; "use strict";
var salt = "Eech7co8Ohloopo9Ol6baimi", var salt = "Eech7co8Ohloopo9Ol6baimi",
location = window.location.pathname; location = function() { return window.location.pathname };
var script, endpoint, var script, endpoint,
js = document.getElementsByTagName("script"); js = document.getElementsByTagName("script");
@ -91,7 +91,7 @@ define(["app/lib/promise", "app/globals"], function(Q, globals) {
var create = function(tid, data) { var create = function(tid, data) {
var deferred = Q.defer(); var deferred = Q.defer();
curl("POST", endpoint + "/new?" + qs({uri: tid || location}), JSON.stringify(data), curl("POST", endpoint + "/new?" + qs({uri: tid || location()}), JSON.stringify(data),
function (rv) { function (rv) {
if (rv.status === 201 || rv.status === 202) { if (rv.status === 201 || rv.status === 202) {
deferred.resolve(JSON.parse(rv.body)); deferred.resolve(JSON.parse(rv.body));
@ -142,7 +142,7 @@ define(["app/lib/promise", "app/globals"], function(Q, globals) {
if (typeof(nested_limit) === 'undefined') { nested_limit = "inf"; } if (typeof(nested_limit) === 'undefined') { nested_limit = "inf"; }
if (typeof(parent) === 'undefined') { parent = null; } if (typeof(parent) === 'undefined') { parent = null; }
var query_dict = {uri: tid || location, after: lastcreated, parent: parent}; var query_dict = {uri: tid || location(), after: lastcreated, parent: parent};
if(limit !== "inf") { if(limit !== "inf") {
query_dict['limit'] = limit; query_dict['limit'] = limit;
@ -193,7 +193,7 @@ define(["app/lib/promise", "app/globals"], function(Q, globals) {
var feed = function(tid) { var feed = function(tid) {
return endpoint + "/feed?" + qs({uri: tid || location}); return endpoint + "/feed?" + qs({uri: tid || location()});
}; };
var preview = function(text) { var preview = function(text) {

View File

@ -12,10 +12,16 @@ require(["app/lib/ready", "app/config", "app/i18n", "app/api", "app/isso", "app/
jade.set("pluralize", i18n.pluralize); jade.set("pluralize", i18n.pluralize);
jade.set("svg", svg); jade.set("svg", svg);
domready(function() { var isso_thread;
var heading;
if (config["css"]) { function init() {
isso_thread = $('#isso-thread');
heading = $.new("h4");
if (config["css"] && $("style#isso-style") === null) {
var style = $.new("style"); var style = $.new("style");
style.id = "isso-style";
style.type = "text/css"; style.type = "text/css";
style.textContent = css.inline; style.textContent = css.inline;
$("head").append(style); $("head").append(style);
@ -23,27 +29,30 @@ require(["app/lib/ready", "app/config", "app/i18n", "app/api", "app/isso", "app/
count(); count();
if ($("#isso-thread") === null) { if (isso_thread === null) {
return console.log("abort, #isso-thread is missing"); return console.log("abort, #isso-thread is missing");
} }
if (config["feed"]) { if (config["feed"]) {
var feedLink = $.new('a', i18n.translate('atom-feed')); var feedLink = $.new('a', i18n.translate('atom-feed'));
var feedLinkWrapper = $.new('span.isso-feedlink'); var feedLinkWrapper = $.new('span.isso-feedlink');
feedLink.href = api.feed($("#isso-thread").getAttribute("data-isso-id")); feedLink.href = api.feed(isso_thread.getAttribute("data-isso-id"));
feedLinkWrapper.appendChild(feedLink); feedLinkWrapper.append(feedLink);
$("#isso-thread").append(feedLinkWrapper); isso_thread.append(feedLinkWrapper);
} }
$("#isso-thread").append($.new('h4')); isso_thread.append(heading);
$("#isso-thread").append(new isso.Postbox(null)); isso_thread.append(new isso.Postbox(null));
$("#isso-thread").append('<div id="isso-root"></div>'); isso_thread.append('<div id="isso-root"></div>');
}
api.fetch($("#isso-thread").getAttribute("data-isso-id"), function fetchComments() {
$('#isso-root').textContent = '';
api.fetch(isso_thread.getAttribute("data-isso-id") || location.pathname,
config["max-comments-top"], config["max-comments-top"],
config["max-comments-nested"]).then( config["max-comments-nested"]).then(
function(rv) { function (rv) {
if (rv.total_replies === 0) { if (rv.total_replies === 0) {
$("#isso-thread > h4").textContent = i18n.translate("no-comments"); heading.textContent = i18n.translate("no-comments");
return; return;
} }
@ -51,14 +60,14 @@ require(["app/lib/ready", "app/config", "app/i18n", "app/api", "app/isso", "app/
var count = rv.total_replies; var count = rv.total_replies;
rv.replies.forEach(function(comment) { rv.replies.forEach(function(comment) {
isso.insert(comment, false); isso.insert(comment, false);
if(comment.created > lastcreated) { if (comment.created > lastcreated) {
lastcreated = comment.created; lastcreated = comment.created;
} }
count = count + comment.total_replies; count = count + comment.total_replies;
}); });
$("#isso-thread > h4").textContent = i18n.pluralize("num-comments", count); heading.textContent = i18n.pluralize("num-comments", count);
if(rv.hidden_replies > 0) { if (rv.hidden_replies > 0) {
isso.insert_loader(rv, lastcreated); isso.insert_loader(rv, lastcreated);
} }
@ -70,5 +79,16 @@ require(["app/lib/ready", "app/config", "app/i18n", "app/api", "app/isso", "app/
console.log(err); console.log(err);
} }
); );
}
domready(function() {
init();
fetchComments();
}); });
window.Isso = {
init: init,
fetchComments: fetchComments
};
}); });