Comment icon indicating copy to clipboard operation
Comment copied to clipboard

Comment pagination without reloading the page

Open ChathuraGH opened this issue 2 years ago • 30 comments

Proposed Functionality

You can post, edit, flag, delete comments without refreshing page. But you can't go to paginated pages without refreshing. How come you can post, but can't load next page with ajax or fetch. My propose is to use ajax/fetch to load paginated pages.

Use Case

Types >

  1. auto loadwith scroll with ajax/fetch > no click needed
  2. keep current pagination links, but load with ajax/fetch > onclick on link

Changes

Only small js code need to be changed. I can create a pull request if you want.

ChathuraGH avatar Dec 15 '23 14:12 ChathuraGH

This is a very useful suggestion. We'll be looking forward to it. @ChathuraGH , please tell me, without PR, what changes do I need to make in order for the "Load more" button to appear? (I'm a beginner developer, I'll be grateful)

ogurec-ogurec avatar Dec 16 '23 09:12 ogurec-ogurec

@ogurec-ogurec , What version do you use? django-comments-dab version. because answer changes with version.

ChathuraGH avatar Dec 18 '23 19:12 ChathuraGH

For django-comments-dab==1.6.7

@ogurec-ogurec , @Radi85 .

I have spend some time for the task now. Maybe there are lot of variations in this design. As

  1. use ajax(jQuery)
  2. use fetch
  3. not query full page(medium code change)
  4. use iframe
  5. use auto load on scroll > no buttons, no clicks, infinity scroll
  6. use more button to load onclick
  7. use pagination buttons to replace content
  8. query full page(small code changes) . So anything is possible. It is just a matter of work that you have to put in to. Every combination has its own pros and cons. So for now, I have used option 2,8,6.

@ogurec-ogurec , @Radi85

Steps

1)

  1. Select one of your django apps
  2. go to template folder
  3. create folder 'comment'
  4. go in to this folder
  5. create folder 'comments'
  6. go in to this folder
  7. create 'pagination.html' file
  8. put the below code in this file

<nav id="pagination-nav" aria-label="Page navigation" class="mt-3 mb-5">
    <ul class="pagination justify-content-center pagination-sm">

        {% if comments.has_next %}
            <li class="{{li_cls}}">
                <a class="page-link {{text_style}}" onclick="event.preventDefault();Load_Commentsx(this);" href="?page={{ comments.next_page_number }}#comments" style="color:blue;font-weight:bold;font-size:large;" aria-label="Next">
                    Get More Comments
                </a>
            </li class="{{li_cls}}">
        {% endif %}
    </ul>
</nav>


2)

  1. Put below code inside(anywhere) your template(where you render your comments) > best if put at the bottom of page

<script type="text/javascript">
function Load_Commentsx(e){
    var q_url=e.href;
    let response = fetch(q_url).then(function(response) {
        if (response.ok) {
            response.text().then(function(text) {
                document.querySelector('#pagination-nav').remove();
                document.querySelector('#Modal').remove();
                const template = document.createElement('template');
                template.innerHTML = text;
                var elem=document.querySelector('#comments div.js-main-comment');
                const lightBoxContent1 = template.content.querySelector('#comments div.js-main-comment');
                elem.innerHTML = elem.innerHTML + lightBoxContent1.innerHTML;
                var elem2=document.querySelector('#comments');
                const lightBoxContent2 = template.content.querySelector('#comments #Modal');
                elem2.appendChild(lightBoxContent2);
                const lightBoxContent3 = template.content.querySelector('#comments #pagination-nav');
                elem2.appendChild(lightBoxContent3);
            });
        }
    });
};
</script>


3)

Render your comments as usual.

Happy Coding.💓⭐⚡😀.

ChathuraGH avatar Dec 18 '23 20:12 ChathuraGH

@ChathuraGH wow, big thanks, I struggled for almost a week to implement something like this. I ran off to test it, I'll come back with feedback.

ogurec-ogurec avatar Dec 20 '23 13:12 ogurec-ogurec

I am excited to see your feedback 👀.

ChathuraGH avatar Dec 20 '23 14:12 ChathuraGH

@ChathuraGH I tested it, added the code to the file site-packages\comment\templates\comment\comments\pagination.html, the button appeared, the button has the desired value of the next page in the link, but when clicked, nothing is loaded, and there is an error in the console: Uncaught (in promise) TypeError: Cannot read properties of null (reading 'innerHTML')

here in this line: image

apparently, there's something wrong with the selectors.

DAB version: v2.8.0 (last)

ogurec-ogurec avatar Dec 21 '23 23:12 ogurec-ogurec

Somewhat expected behaviour, because I didn't know your version. I will post working code for your version.

ChathuraGH avatar Dec 22 '23 03:12 ChathuraGH

@ogurec-ogurec , @Radi85 . I just tested for your(@ogurec-ogurec ) version(DAB version: v2.8.0 (last)). It works.

JS CODE


<script type="text/javascript">
function Load_Commentsx(e){
    var q_url=e.href;
    let response = fetch(q_url).then(function(response) {
        if (response.ok) {
            response.text().then(function(text) {

// remove > #pagination-nav + #Modal
                document.querySelector('#pagination-nav').remove();
                document.querySelector('#Modal').remove();
// template
               var template = document.createElement('template');
                template.innerHTML = text;
// add new comments
                var old_comments=document.querySelector(''section#comments div.mt-5');
                const new_comments_section= template.content.querySelector('section#comments div.mt-5');
                old_comments.innerHTML = old_comments.innerHTML + new_comments_section.innerHTML;
///////
                var elem2=document.querySelector('#comments');
//2 add new #Modal
                var new_Modal = template.content.querySelector('#comments #Modal');
                elem2.appendChild(new_Modal );
//3 add new #pagination-nav
                var new_pagination_nav = template.content.querySelector('#comments #pagination-nav');
                elem2.appendChild(new_pagination_nav );
            });
        }
    });
};
</script>

TEMPLATE CODE


{% load i18n %}
<nav id="pagination-nav" aria-label={% trans "Page navigation" %} class="mt-3 mb-5">
	{% trans "Get More Comments" as Get_More_Comments %}
    <ul class="pagination justify-content-center pagination-sm">
        {% if comments.has_next %}
            <li class="{{li_cls}}">
                <a class="page-link {{text_style}}" onclick="event.preventDefault();Load_Commentsx(this);" href="?page={{ comments.next_page_number }}#comments" style="color:blue;font-weight:bold;font-size:large;" aria-label={{ Get_More_Comments }}>
                    {{ Get_More_Comments }}
                </a>
            </li class="{{li_cls}}">
        {% endif %}
    </ul>
</nav>

Happy Coding.💓⭐⚡😀.

ChathuraGH avatar Dec 23 '23 04:12 ChathuraGH

What happened bro? Did you succeed?

ChathuraGH avatar Dec 25 '23 18:12 ChathuraGH

@ChathuraGH thanks the code, i add code to the pagination.html, but there is an error when starting:

image

here in this line:

  <a class="page-link text-success" onclick="event.preventDefault();Load_Commentsx(this);" href="?page=2#comments" style="color:blue;font-weight:bold;font-size:large;" aria-label=Get More Comments>
                    Get More Comments
                </a>

what could it be?

ogurec-ogurec avatar Dec 26 '23 11:12 ogurec-ogurec

I know what it is. Where did you put JS CODE? This happens when js code is not present.

ChathuraGH avatar Dec 26 '23 12:12 ChathuraGH

That's it, I found a mistake, there was one extra quote,

var old_comments=document.querySelector(''section#comments div.mt-5');

, now it works, but a new problem has appeared, after the comments are loaded from the second page, the button and pagination disappear, and the comments are no longer loaded. Roughly speaking, comments are loaded only from the second page, although there are many more comments

ogurec-ogurec avatar Dec 26 '23 12:12 ogurec-ogurec

ok.... I see it now..

ChathuraGH avatar Dec 26 '23 12:12 ChathuraGH

can you try removing spaces here..

        elem2.appendChild(new_Modal );<<<<<
        //3 add new #pagination-nav
        var new_pagination_nav = template.content.querySelector('#comments #pagination-nav');
        elem2.appendChild(new_pagination_nav );<<<<

ChathuraGH avatar Dec 26 '23 13:12 ChathuraGH

The below code works for me, bro..

// with support to DAB version: v2.8.0 (last)(2023/12)
function Load_Commentsx(e){
  var q_url=e.href;
  let response = fetch(q_url).then(function(response) {
    if (response.ok) {
      response.text().then(function(text) {
        // remove > #pagination-nav + #Modal
        document.querySelector('#pagination-nav').remove();
        document.querySelector('#Modal').remove();
        // template
        var template = document.createElement('template');
        template.innerHTML = text;
        // add new comments
        var old_comments=document.querySelector('section#comments div.mt-5');
        const new_comments_section= template.content.querySelector('section#comments div.mt-5');
        old_comments.innerHTML = old_comments.innerHTML + new_comments_section.innerHTML;
        ///////
        var elem2=document.querySelector('#comments');
        //2 add new #Modal
        var new_Modal = template.content.querySelector('#comments #Modal');
        elem2.appendChild(new_Modal);
        //3 add new #pagination-nav
        var new_pagination_nav = template.content.querySelector('#comments #pagination-nav');
        elem2.appendChild(new_pagination_nav);
      });
    }
  });
};

ChathuraGH avatar Dec 26 '23 13:12 ChathuraGH

@ChathuraGH only the second page of comments will load, after which the link in the button will not change and the paginator disappears, it seems that this is the case - the paginator disappears and the number in the button does not change (

ogurec-ogurec avatar Dec 26 '23 13:12 ogurec-ogurec

What is disappearing? the paginator disappears and the number in the button does not change? There is only one button. if it disappeared, how do you know "number in the button does not change"?

ChathuraGH avatar Dec 26 '23 13:12 ChathuraGH

@ChathuraGH I added a button to the existing pagination, after loading one page the button disappears and an error appears:

newpost:2263 Uncaught (in promise) TypeError: Failed to execute 'appendChild' on 'Node': parameter 1 is not of type 'Node'. here in this line: elem2.appendChild(new_Modal); comment_test1

ogurec-ogurec avatar Dec 26 '23 14:12 ogurec-ogurec

I added a button to the existing pagination? How did you do that?

{% load i18n %}
<nav id="pagination-nav" aria-label={% trans "Page navigation" %} class="mt-3 mb-5">
	{% trans "Get More Comments" as Get_More_Comments %}
    <ul class="pagination justify-content-center pagination-sm">
        {% if comments.has_next %}
            <li class="{{li_cls}}">
                <a class="page-link {{text_style}}" onclick="event.preventDefault();Load_Commentsx(this);" href="?page={{ comments.next_page_number }}#comments" style="color:blue;font-weight:bold;font-size:large;" aria-label={{ Get_More_Comments }}>
                    {{ Get_More_Comments }}
                </a>
            </li class="{{li_cls}}">
        {% endif %}
    </ul>
</nav>

What parts did you include or exclude from above code?

I coded it to replace old template.

ChathuraGH avatar Dec 26 '23 14:12 ChathuraGH

Just replace the content of the template. You can't use both(pagi number buttons and lode more button) with my js code.

ChathuraGH avatar Dec 26 '23 14:12 ChathuraGH

@ChathuraGH I replaced all the code in the \Lib\site-packages\comment\templates\comment\comments\pagination.html file: here is the full code:

{% load i18n %}
<nav id="pagination-nav" aria-label={% trans "Page navigation" %} class="mt-3 mb-5">
	{% trans "Get More Comments" as Get_More_Comments %}
    <ul class="pagination justify-content-center pagination-sm">
        {% if comments.has_next %}
            <li class="{{li_cls}}">
                <a class="page-link {{text_style}}" onclick="event.preventDefault();Load_Commentsx(this);" href="?page={{ comments.next_page_number }}#comments" style="color:blue;font-weight:bold;font-size:large;" aria-label={{ Get_More_Comments }}>
                    {{ Get_More_Comments }}
                </a>
            </li class="{{li_cls}}">
        {% endif %}
    </ul>
</nav>





<script type="text/javascript">
// with support to DAB version: v2.8.0 (last)(2023/12)
function Load_Commentsx(e){
  var q_url=e.href;
  let response = fetch(q_url).then(function(response) {
    if (response.ok) {
      response.text().then(function(text) {
        // remove > #pagination-nav + #Modal
        document.querySelector('#pagination-nav').remove();
        document.querySelector('#Modal').remove();
        // template
        var template = document.createElement('template');
        template.innerHTML = text;
        // add new comments
        var old_comments=document.querySelector('section#comments div.mt-5');
        const new_comments_section= template.content.querySelector('section#comments div.mt-5');
        old_comments.innerHTML = old_comments.innerHTML + new_comments_section.innerHTML;
        ///////
        var elem2=document.querySelector('#comments');
        //2 add new #Modal
        var new_Modal = template.content.querySelector('#comments #Modal');
        elem2.appendChild(new_Modal);
        //3 add new #pagination-nav
        var new_pagination_nav = template.content.querySelector('#comments #pagination-nav');
        elem2.appendChild(new_pagination_nav);
      });
    }
  });
};
</script>

When you click on the "load more" button, only the second page is loaded, after which the button disappears and an error appears in the console:

Uncaught (in promise) TypeError: Failed to execute 'appendChild' on 'Node': parameter 1 is not of type 'Node'.
    at eeee:2206:15

image

ogurec-ogurec avatar Dec 26 '23 14:12 ogurec-ogurec

bro I told you to put js code in your main template. not in pagination template. 1) Put js code just inside template you are loading comments. like after {% include_bootstrap %}.

ChathuraGH avatar Dec 26 '23 15:12 ChathuraGH

@ChathuraGH placed in the template, a similar error after loading 2 pages:


Uncaught (in promise) TypeError: Failed to execute 'appendChild' on 'Node': parameter 1 is not of type 'Node'.
    at eeee:2296:15

image

try to reproduce the error: create more than 3 pages of comments

ogurec-ogurec avatar Dec 26 '23 15:12 ogurec-ogurec

@ChathuraGH it worked, it seems,

replaced the line elem2.appendChild(new_Modal); in elem2.appendChild(document.createElement(new_Modal));

and delete line: document.querySelector('#Modal').remove();

thanks for the help

ogurec-ogurec avatar Dec 26 '23 15:12 ogurec-ogurec

@ChathuraGH I have several questions, the first one:

  1. Is it safe to insert content on the page (innerHTML) like this?
  2. How can a preloader be implemented?

ogurec-ogurec avatar Dec 26 '23 15:12 ogurec-ogurec

  1. yes.
  2. you mean to load all comments at once?

ChathuraGH avatar Dec 26 '23 15:12 ChathuraGH

@ChathuraGH I mean how to add a “loading..” animation, like for example on YouTube, when you click “Load comments” a preloader appears until the comments are loaded

image

ogurec-ogurec avatar Dec 26 '23 16:12 ogurec-ogurec

It's easy.

  1. Download/creat your loading animation (image or gif or css)
  2. if it's image or gif add it to your static files / if it's css just use html
  3. append it like below
  4. remove it after successful load comments
<script type="text/javascript">
// with support to DAB version: v2.8.0 (last)(2023/12)
function Load_Commentsx(e){
  var q_url=e.href;




// append your image/gif/css

if(document.querySelector('#loading')){
}
else{
    var elem0=document.querySelector('#comments');
    var new_Modal =document.createElement('your html with id==loading');
    elem0.appendChild(new_Modal);
}




  let response = fetch(q_url).then(function(response) {
    if (response.ok) {
      response.text().then(function(text) {
        // remove > #pagination-nav + #Modal
        document.querySelector('#pagination-nav').remove();
        document.querySelector('#Modal').remove();
        // template
        var template = document.createElement('template');
        template.innerHTML = text;
        // add new comments
        var old_comments=document.querySelector('section#comments div.mt-5');
        const new_comments_section= template.content.querySelector('section#comments div.mt-5');
        old_comments.innerHTML = old_comments.innerHTML + new_comments_section.innerHTML;
        ///////
        var elem2=document.querySelector('#comments');
        //2 add new #Modal
        var new_Modal = template.content.querySelector('#comments #Modal');
        elem2.appendChild(new_Modal);
        //3 add new #pagination-nav
        var new_pagination_nav = template.content.querySelector('#comments #pagination-nav');
        elem2.appendChild(new_pagination_nav);







// Remove your image/gif/css

if(document.querySelector('#loading')){
 document.querySelector('#loading').remove();
}









      });
    }
  });
};
</script>

ChathuraGH avatar Dec 27 '23 03:12 ChathuraGH

@ChathuraGH thanks for the help, i created

outside of comments :

<div> <img src="https://media.tenor.com/G7LfW0O5qb8AAAAi/loading-gif.gif" id="loading"> </div>

add to scrpit to:

if(document.querySelector('#loading')){
}
else{
    var elem0=document.querySelector('#comments');
    var new_Modal =document.createElement('your html with id=loading');
    elem0.appendChild(new_Modal);
}
        // Remove your image/gif/css

if(document.querySelector('#loading')){
 document.querySelector('#loading').remove();
}

erorr: Uncaught DOMException: Failed to execute 'createElement' on 'Document': The tag name provided ('your html with id=loading') is not a valid name.

did do something wrong?

ogurec-ogurec avatar Dec 28 '23 17:12 ogurec-ogurec

bro I actually can't believe you ran this line.var new_Modal =document.createElement('your html with id=loading'); ..

I will post working code.

ChathuraGH avatar Dec 28 '23 18:12 ChathuraGH