D
D
Dmitry Temnikov2021-01-24 15:31:48
JavaScript
Dmitry Temnikov, 2021-01-24 15:31:48

How to make posts autoload on scroll?

Good afternoon comrades! I decided to use Ajax on my pet project to automatically load the publication. It seems to load, but there are a couple of problems that I can’t solve in any way

A piece of the publications.html template
<nowrap id="publoader">
    <div class="col-md-12">
        <div class="alert alert-info">
          <div class="clearfix">Загрузка публикаций ...
            <div class="spinner-border float-right" role="status">
              <span class="sr-only">Загрузка публикаций ...</span>
            </div>
          </div>
        </div>
    </div>
    <script type="text/javascript">
        window.addEventListener('scroll', function() {
        let windowRelativeBottom = document.documentElement.getBoundingClientRect().bottom;
        if (windowRelativeBottom < document.documentElement.clientHeight + 100) {
          var myDiv = document.getElementById("publoader");
          $.ajax({
                url: "/mytestblog/ajaxMorePub?cat={{ cat_id_join }}{% if tag.0 != "" %}&tag={{ tagstr_param }}{% endif %}&page={{ page }}&size={{ size }}&order={{ order }}&direction={{ direction }}",
                success: function(data){
                  myDiv.id="pass";
                  myDiv.innerHTML=data;
                                       }
                  });
                                                                                }
        });
    </script>
</nowrap>
ajaxMorePub.html template (same, but with content loading)
{% include "pubcontent.html" %}
<nowrap id="publoader">
    <div class="col-md-12">
        <div class="alert alert-info">
          <div class="clearfix">Загрузка публикаций ...
            <div class="spinner-border float-right" role="status">
              <span class="sr-only">Загрузка публикаций ...</span>
            </div>
          </div>
        </div>
    </div>
    <script type="text/javascript">
        window.addEventListener('scroll', function() {
        let windowRelativeBottom = document.documentElement.getBoundingClientRect().bottom;
        if (windowRelativeBottom < document.documentElement.clientHeight + 100) {
          var myDiv = document.getElementById("publoader");
          $.ajax({
                url: "/mytestblog/ajaxMorePub?cat={{ cat_id_join }}{% if tag.0 != "" %}&tag={{ tagstr_param }}{% endif %}&page={{ page }}&size={{ size }}&order={{ order }}&direction={{ direction }}",
                success: function(data){
                  myDiv.id="pass";
                  myDiv.innerHTML=data;
                                       }
                  });
                                                                                }
        });
    </script>
</nowrap>

View that handles both requests
def pubcontent(request, template):
    cat_id = request.GET.get("cat", '0')
    tag = request.GET.get("tag", "")
    page = request.GET.get("page", 1)
    order = request.GET.get("order", 'date')
    direction = request.GET.get("direction", 'DESC')
    size = request.GET.get("size", 5)
======================================
    # обработка параметра page
    try: page=int(page)
    except Exception:
        page=1
    if page<1:
        page=1
    if template == "ajaxMorePub.html":
        page += 1 
========================================
# получаем список pub_id по параметрам
    pubidlist=get_pub_id_by_params(cat_id=set(cat_id), tag=set(tag),
                    order=order, direction=direction)
# осуществляем пагинацию
    paginator = Paginator(pubidlist, size)
    if page>paginator.num_pages:
        page=paginator.num_pages
    pubidlist = paginator.get_page(page)
# запрашиваем модель данных
    pubmodel=get_pub_model(pubidlist,
        order=order, direction=direction)
=========================================
    return render(request, template, {
            'categories': catlist,
            'pub_sorted': pubmodel.items(),
            'cat_param': cat_name.replace(", ", ","),
            'cat_name': cat_name,
            'cat_id_join': ",".join(str(elem) for elem in cat_id),
            'cat_id': cat_id,
            'tags': taglist,
            'order': order, 'size': size, 'direction': direction,
            'page_range': paginator.page_range,
            'num_pages': paginator.num_pages,
            'paginator': paginator.page(page),
            'page': page,
            'tagstr_param': tagstr.replace(", ", ","),
            'tagstr_header': tagstr,
            'tag':tag
        })


def publications(request):
    pub_content = pubcontent(request, template="publications.html")
    return pub_content

def ajaxMorePub(request):
    pub_content = pubcontent(request, template="ajaxMorePub.html")
    return pub_content

I removed the extra pieces, sometimes crutches, but it's necessary :-) The code shows that the view increments the page for the ajaxMorePub.html template.

What we have as a result: the page is loading, we scroll to the scroll wheel, the second page is successfully loaded. But then the jokes
Problem number 1. For some reason, the spinner loads the second page every time, does not move forward. If you open the page directly in the browser /mytestblog/ajaxMorePub/?cat=0&page=1&size=5&order=date&direction=DESC, then you can see that the view is working, there is content on the second page, the script honestly says /mytestblog/ajaxMorePub/?cat=0&page=2&size =5&order=date&direction=DESC
But when all this returns /mytestblog/publication/, then when myDiv.innerHTML=data is inserted, the content of the second page is loaded, but for some reason the script is not there, it still contains /mytestblog/ajaxMorePub/?cat=0&page=1&size=5&order= date&direction=DESC. As a result, we go in a circle
Problem number 2. Actually, the scrolling itself repeatedly pulls ajaxMorePub.html, this can be seen from the Django console. How to make it twitch once per download?

Answer the question

In order to leave comments, you need to log in

1 answer(s)
D
Dmitry Temnikov, 2021-01-26
@exibit777

Decided as follows

A piece of the publication.html template
{% block сontent %}
    <nowrap id="contentBlock">
        {% include "pubcontent.html" %}
    </nowrap>
    <div class="col-md-12">
        <div class="alert alert-info">
          <div class="clearfix">Загрузка публикаций ...
            <div class="spinner-border float-right" role="status">
              <span class="sr-only">Загрузка публикаций ...</span>
            </div>
          </div>
        </div>
    </div>
    <script type="text/javascript">
        window.need_load_more=1;
        window.need_page=2;
        window.addEventListener('scroll', function() {
        let windowRelativeBottom = document.documentElement.getBoundingClientRect().bottom;
        if (windowRelativeBottom < document.documentElement.clientHeight + 100) {
            if (window.need_load_more == 1) {
                window.need_load_more = 0;
            var myDiv = document.getElementById("contentBlock");
            $.ajax({
                url: "/mytestblog/pubcontent?cat={{ cat_id_join }}{% if tag.0 != "" %}&tag={{ tagstr_param }}{% endif %}&page=" + window.need_page + "&size={{ size }}&order={{ order }}&direction={{ direction }}",
                success: function(data){
                  myDiv.insertAdjacentHTML('beforeEnd', data);
                  window.need_page = window.need_page + 1;
                  window.need_load_more = 1;
                                       }
                  });
            };                                                                     }
        });
    </script>
{% endblock %}

1. The script is taken out of the block, instead of innerHTML I use insertAdjacentHTML
2. Accordingly, a separate ajaxMorePub.html template is not needed, the script uses the same pubcontent.html template as the contentBlock element in which this content is added
3. pubcontent was added to url.py accordingly .html
4. The script is now doing the increment, not the view
5. The global flag solves the problem of multiple requests

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question