From 8690226ec041c28a21cb5267b69632ecc280a089 Mon Sep 17 00:00:00 2001 From: HombreLaser Date: Tue, 27 Feb 2024 11:18:43 -0600 Subject: Improve coments pagination --- static/js/controllers/base_controller.js | 40 ++++++------- static/js/controllers/comments_controller.js | 39 ++++++------ static/js/controllers/pagination_controller.js | 52 ++++++++++++++++ static/js/controllers/replies_controller.js | 82 +++++++++++++------------- static/js/paginator.js | 15 ----- 5 files changed, 133 insertions(+), 95 deletions(-) create mode 100644 static/js/controllers/pagination_controller.js delete mode 100644 static/js/paginator.js diff --git a/static/js/controllers/base_controller.js b/static/js/controllers/base_controller.js index 2ef359c..40a16ca 100644 --- a/static/js/controllers/base_controller.js +++ b/static/js/controllers/base_controller.js @@ -1,5 +1,5 @@ export class BaseController { - constructor() { + constructor() { this.comments_server_url = document.getElementById('comments-client').src; this.origin = window.location.origin; this.protocol = this.getProtocol(); @@ -7,39 +7,39 @@ export class BaseController { this.post = window.location.pathname; this.comments_server_host = `${this.protocol}//${this.domain}`; this.parser = new DOMParser(); - } + } - async submit(event, route, form = new FormData(event.target)) { + async submit(event, route, form = new FormData(event.target)) { event.preventDefault(); try { - const response = await fetch(route, { method: "POST", body: form }); + const response = await fetch(route, { method: "POST", body: form }); - response.text().then((response_document) => { + response.text().then((response_document) => { this.renderSubmitResponse(response_document); - }); - } catch(error) {} - } + }); + } catch (error) { } + } - getDomain() { + getDomain() { return this.comments_server_url.split('/')[2]; - } + } - getProtocol() { + getProtocol() { return this.comments_server_url.split('/')[0]; - } + } - htmlFromResponse(body) { + htmlFromResponse(body) { return this.parser.parseFromString(body, "text/html"); - } + } - async get(route) { + async get(route) { try { - const response = await fetch(`${this.comments_server_host}${route}`); + const response = await fetch(`${this.comments_server_host}${route}`); - return response.text().then(this.htmlFromResponse.bind(this)); - } catch(error) { - return null; + return response.text().then(this.htmlFromResponse.bind(this)); + } catch (error) { + return null; } - } + } } diff --git a/static/js/controllers/comments_controller.js b/static/js/controllers/comments_controller.js index 683f5ca..86abfe6 100644 --- a/static/js/controllers/comments_controller.js +++ b/static/js/controllers/comments_controller.js @@ -1,51 +1,52 @@ import { BaseController } from "./base_controller.js"; -import { Paginator } from "../paginator.js"; +import { PaginationController } from "./pagination_controller.js"; export class CommentsController extends BaseController { - constructor(replies_controller) { + constructor(replies_controller) { super(); this.replies_controller = replies_controller; this.comments_node = document.getElementById("comments-thread"); - this.paginator = new Paginator(this.comments_server_host, "/api/comments", this.post); + this.paginator = new PaginationController(this.comments_server_host, "/api/comments", this.post, + this.replies_controller); this.renderForm(); this.renderComments(); - } + } - renderForm() { + renderForm() { this.get("/api/comments/new").then((value) => { - const form = value?.getElementById("comment-form"); + const form = value?.getElementById("comment-form"); - if(form != null) { + if (form != null) { this.comments_node.appendChild(form); this.form_element = document.getElementById("comment-form"); this.form_element.addEventListener("submit", this.submit.bind(this)); - } + } }); - } + } - renderComments() { + renderComments() { this.get(`/api/comments?path=${this.post}`).then((value) => { - const comments = value?.getElementById("comment-section"); + const comments = value?.getElementById("comment-section"); - if(comments != null) { + if (comments != null) { this.comments_node.appendChild(comments); this.replies_controller.init(); this.paginator.populatePageAnchors(); - } + } }); - } + } - renderSubmitResponse(response_document) { + renderSubmitResponse(response_document) { const new_comments = this.htmlFromResponse(response_document).getElementById("comment-section"); const comments = document.getElementById("comment-section"); comments.replaceWith(new_comments); - } + } - async submit(event) { + async submit(event) { var form = new FormData(event.target); form.append("domain", `${window.location.protocol}//${window.location.host}`); super.submit(event, `${this.comments_server_host}/api/comments?path=${this.post}`, form); - } - } + } +} diff --git a/static/js/controllers/pagination_controller.js b/static/js/controllers/pagination_controller.js new file mode 100644 index 0000000..bfb1a48 --- /dev/null +++ b/static/js/controllers/pagination_controller.js @@ -0,0 +1,52 @@ +import { BaseController } from "./base_controller.js"; + +export class PaginationController extends BaseController { + constructor(host, context, path, replies_controller) { + super(); + this.replies_controller = replies_controller; + this.endpoint = `${host}${context}?path=${path}`; + this.comments_node = document.getElementById("comments-thread"); + } + + populatePageAnchors() { + const pagination_widget = document.querySelector(".pagination"); + var anchors = pagination_widget.querySelectorAll('a'); + + for (let anchor of anchors) { + var page = /\d/.exec(anchor.id)[0]; + anchor.setAttribute("href", `${this.endpoint}&page=${page}`); + } + + this.listenForPageChange(anchors); + } + + listenForPageChange(page_selectors) { + for (let anchor of page_selectors) { + anchor.addEventListener("click", this.changeCommentsPage.bind(this)) + } + } + + changeCommentsPage(event) { + event.preventDefault(); + + fetch(event.target.getAttribute("href")) + .then((response) => { + return response.text(); + }) + .then((data) => { + this.loadComments(this.htmlFromResponse(data)); + }); + } + + loadComments(body) { + const previous_comments = document.getElementById("comment-section"); + const comments = body?.getElementById("comment-section"); + + if(comments) { + previous_comments.remove(); + this.comments_node.appendChild(comments); + this.replies_controller.init(); + this.populatePageAnchors(); + } + } +} \ No newline at end of file diff --git a/static/js/controllers/replies_controller.js b/static/js/controllers/replies_controller.js index c383e57..dfcafb2 100644 --- a/static/js/controllers/replies_controller.js +++ b/static/js/controllers/replies_controller.js @@ -1,70 +1,70 @@ import { BaseController } from "./base_controller.js"; export class RepliesController extends BaseController { - constructor() { + constructor() { super(); - } + } - async init() { + async init() { this.comment_id = 0; this.reply_form = await this.getReplyForm(); this.listenButtons("replies-button", this.renderReplies.bind(this)); this.listenButtons("new-reply-button", this.showReplyForm.bind(this)); - } + } - async submit(event) { + async submit(event) { await super.submit(event, `${this.comments_server_host}/api/comments/${this.comment_id}/replies`); - } + } - listenButtons(class_name, func) { + listenButtons(class_name, func) { const buttons = document.getElementsByClassName(class_name); - if(buttons) { - for(let button of buttons) + if (buttons) { + for (let button of buttons) button.addEventListener("click", func); } - } + } - showReplyForm(event) { + showReplyForm(event) { const replies_section = event.target.parentElement.parentElement.childNodes[3]; const form = replies_section.querySelector(".reply-form"); - if(form == null) { - replies_section.appendChild(this.reply_form); - this.setCommentId(replies_section); - this.reply_form.addEventListener("submit", this.submit.bind(this)); + if (form == null) { + replies_section.appendChild(this.reply_form); + this.setCommentId(replies_section); + this.reply_form.addEventListener("submit", this.submit.bind(this)); } else - form.remove(); - } + form.remove(); + } - renderReplies(event) { - /* The div to contain the comment's replies. From the element id - we can get the comment's id. */ - const comment_replies_section = event.target.parentElement.parentElement.parentElement; - const present_replies = comment_replies_section.querySelector(".replies-section"); - this.setCommentId(comment_replies_section); + renderReplies(event) { + /* The div to contain the comment's replies. From the element id + we can get the comment's id. */ + const comment_replies_section = event.target.parentElement.parentElement.parentElement; + const present_replies = comment_replies_section.querySelector(".replies-section"); + this.setCommentId(comment_replies_section); - if(present_replies != null) { - present_replies.remove(); + if (present_replies != null) { + present_replies.remove(); - return; - } + return; + } + + this.get(`/api/comments/${this.comment_id}/replies`).then((value) => { + const replies = value?.getElementById(`replies-section-${this.comment_id}`); - this.get(`/api/comments/${this.comment_id}/replies`).then((value) => { - const replies = value?.getElementById(`replies-section-${this.comment_id}`); - - if(replies != null) - comment_replies_section.appendChild(replies); - }); - } + if (replies != null) + comment_replies_section.appendChild(replies); + }); + } - setCommentId(replies_section) { - this.comment_id = /\d/.exec(replies_section.id)[0]; - } + setCommentId(replies_section) { + this.comment_id = /\d/.exec(replies_section.id)[0]; + } - async getReplyForm() { - var form = await this.get("/api/replies/new"); + async getReplyForm() { + var form = await this.get("/api/replies/new"); - return form.getElementsByClassName("reply-form")[0]; - } + return form.getElementsByClassName("reply-form")[0]; + } } diff --git a/static/js/paginator.js b/static/js/paginator.js deleted file mode 100644 index 9a7ed65..0000000 --- a/static/js/paginator.js +++ /dev/null @@ -1,15 +0,0 @@ -export class Paginator { - constructor(host, context, path) { - this.endpoint = `${host}${context}?path=${path}`; - } - - populatePageAnchors() { - const pagination_widget = document.querySelector(".pagination"); - var anchors = pagination_widget.querySelectorAll('a'); - - for(let anchor of anchors) { - var page = /\d/.exec(anchor.id)[0]; - anchor.setAttribute("href", `${this.endpoint}&page=${page}`); - } - } -} \ No newline at end of file -- cgit v1.2.3