0

In my web site I want to show the user ratings - for that I used the infinite scroll but I am facing one problem.

When it first loads the data before calling the <a class="infinite-more-link" href="?page={{ ratings.next_page_number }}"></a> it is showing the star with the count of vote,but when after calling the <a class="infinite-more-link" href="?page={{ ratings.next_page_number }}"></a> it is not showing the star.

my views.py

@login_required
def ratings_user(request,pk):
    ratings = VoteUser.objects.filter(the_user_id=pk).order_by('-pk')
    paginator = Paginator(ratings, 1)
    page = request.GET.get('page')
    try:
        posts = paginator.page(page)
    except PageNotAnInteger:
        posts = paginator.page(1)
    except EmptyPage:

        posts = paginator.page(paginator.num_pages)
    return render(request,request.session['is_mobile']+'profile/ratings.html',{'ratings':posts})

html

{% extends 'mobile/profile/base.html' %}
{% block title %}
Ratings
{% endblock %}

{% block leftcontent %}
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.9.0/css/all.min.css" rel="stylesheet">
{% endblock %}
{% block middlecontent %}
 <div class="infinite-container">

{% for i in ratings %}
 <div class="infinite-item">
     
<div class="w3-container w3-card w3-white w3-round w3-margin">
    <img src="{{ i.the_user.profile.avatar.url }}" alt="Avatar" class="w3-left w3-circle w3-margin-right" style="width:40px;height:40px;border-radius:50%;">

        <a href ="{% url 'profile' i.the_user_id %}" style="color:black;">{% with user=i.the_user.profile %}{{ user.prenom|title|truncatewords:2 }} {{ user.nom|title|truncatewords:1 }}{% endwith %}</a>
        <br>

       <span class="stars" data-rating="{{ i.vote.vote }}" data-num-stars="5" ></span>
        <hr class="w3-clear">
        <p>
        {{ i.commentaire|linebreaksbr }}
        </p>
        <span class="glyphicon glyphicon-user"></span> <a href ="{% url 'profile' i.the_sender_id %}">{% with user=i.the_sender.profile %}{{ user.prenom|title|truncatewords:2 }} {{ user.nom|title|truncatewords:1 }}{% endwith %}</a>
</div>
</div>
{% endfor %}
</div>
   {% if ratings.has_next %}
    <a class="infinite-more-link" href="?page={{ ratings.next_page_number }}"></a>
  {% endif %}
{% endblock %}
{% block rightcontent %}

{% endblock %}
{% block js %}
  <script>
    var infinite = new Waypoint.Infinite({
      element: $('.infinite-container')[0]
    });
  </script>
<script>
//ES5
$.fn.stars = function() {
    return $(this).each(function() {
        var rating = $(this).data("rating");
        var fullStar = new Array(Math.floor(rating + 1)).join('<i class="fas fa-star"></i>');
        var halfStar = ((rating%1) !== 0) ? '<i class="fas fa-star-half-alt"></i>': '';
        var noStar = new Array(Math.floor($(this).data("numStars") + 1 - rating)).join('<i class="far fa-star"></i>');
        $(this).html(fullStar + halfStar + noStar);
    });
}

//ES6
$.fn.stars = function() {
    return $(this).each(function() {
        const rating = $(this).data("rating");
        const numStars = $(this).data("numStars");
        const fullStar = '<i class="fas fa-star"></i>'.repeat(Math.floor(rating));
        const halfStar = (rating%1!== 0) ? '<i class="fas fa-star-half-alt"></i>': '';
        const noStar = '<i class="far fa-star"></i>'.repeat(Math.floor(numStars-rating));
        $(this).html(`${fullStar}${halfStar}${noStar}`);
    });
}
</script>
<script>
            $(function(){
                $('.stars').stars();
            });
        </script>
{% endblock %}

I have tried to put the <link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.9.0/css/all.min.css" rel="stylesheet"> inside the class="infinite-item" but it does not help.what might be the reason for that ? Thanks.

Since yesterday I am on this question I tried everything.

This is another user that has tried to help me here https://stackoverflow.com/a/69930878/15042684 but I did not really understand could you please help me to understand it with some code.

this is his answer:

It doesn't look like .stars() will look for new elements being added to the DOM. You should look for a callback function configuration option within Waypoint.Infinite that you can call .stars() on the new elements.

freedomn-m
  • 27,664
  • 8
  • 35
  • 57
Thierno Amadou Sow
  • 2,523
  • 2
  • 5
  • 19
  • 1
    `$.fn.stars` *only* applies to elements that exist at the time the code runs. If you add elements later, the code does not automatically pick up the new elements. You need to run `$.fn.stars` on the new elements after they have been added to the DOM. – freedomn-m Nov 12 '21 at 11:00

1 Answers1

1

Assuming you are using waypoint's Infinite Scroll, you can use the onAfterPageLoad callback

onAfterPageLoad

Default: $.noop.

Parameters: $items.

This is a callback that will fire at the end of the request cycle, after new items have been appended to the container. It is passed one parameter, which is a jQuery object of all the items that were appended during the page load.

Note that despite using the jquery convention of $name indicates a jquery object and stating is a jquery object, in this case, trial and error shows that $items are the DOM elements, not a jquery object.

No example provided in the docs, so it will probably look something like:

  <script>
    var infinite = new Waypoint.Infinite({
      element: $('.infinite-container')[0],
      onAfterPageLoad: function(items) {
          $(items).find(".stars").stars();
      } 
    });
  </script>
freedomn-m
  • 27,664
  • 8
  • 35
  • 57
  • how can i pass the items to onAfterPageLoad: function ?i have tried your code but i am not seing the stars rating. – Thierno Amadou Sow Nov 12 '21 at 11:17
  • According to the (very limited) documentation, the newly generated elements are passed in as `$items` (`items)` in my code. But I can't see from you code what that would be - try debugging the callback to see what you're actually getting. Maybe it should be `items.filter(".stars").stars()` - maybe your infinite loader isn't loading any stars? – freedomn-m Nov 12 '21 at 11:30
  • Perhaps you could edit your question and add working snippet in html/css/javascript(jquery)? All the `{% %}` make it overly difficult to read. – freedomn-m Nov 12 '21 at 11:34
  • this is the exception in my browser console `(index):221 Uncaught TypeError: items.find(...).stars is not a function at Object.onAfterPageLoad ((index):221) at t. (infinite.min.js:7) at Object.i [as success] (jquery.min.js:2) at u (jquery.min.js:2) at Object.fireWith [as resolveWith] (jquery.min.js:2) at k (jquery.min.js:2) at XMLHttpRequest. (jquery.min.js:2)` – Thierno Amadou Sow Nov 12 '21 at 11:35
  • Try `onAfterPageLoad: function(items) { $(items).find(".stars").stars(); }` as it looks like the return isn't a jquery object despite the practice of prefixing jquery objects with `$`. Either that or your script tags are in the wrong order and you're blatting your `$.fn.stars` – freedomn-m Nov 12 '21 at 11:37
  • 1
    Thank you very much.God bless you i finally solved it .this was the right function `onAfterPageLoad: function(items) { $(items).find(".stars").stars();` please try to update your answer. – Thierno Amadou Sow Nov 12 '21 at 11:44
  • can i ask you question please ? – Thierno Amadou Sow Nov 15 '21 at 11:06
  • You just did... just ask. If it's not related to this question or answer you'll probably be better off asking it as a new question as it will get better visibility. – freedomn-m Nov 15 '21 at 11:13
  • yes it is related to this,i have the same trouble.i have post and when i load more post the like button is not working,before the load it is working well. – Thierno Amadou Sow Nov 15 '21 at 11:17
  • 1
    You need event delegation. eg instead of `$(".btn").click(...` you need to use `$(document).on("click", ".btn", ...` See [this question](https://stackoverflow.com/questions/203198/event-binding-on-dynamically-created-elements) for more details. – freedomn-m Nov 15 '21 at 11:20
  • can i invite you in a chat please ? – Thierno Amadou Sow Nov 15 '21 at 11:23
  • this is how my like button look like `` and my question now is how can i call on after page load without rewritting all the code inside the like click `$(items).find(".likin").'the-function-that-i-donot-know-how;` – Thierno Amadou Sow Nov 15 '21 at 11:34
  • Thank you and sorry for being so stupid.i tried out the link you sent me and it works fine Thank you again. – Thierno Amadou Sow Nov 15 '21 at 11:56