skip to Main Content

Brief Context: I am trying to create a chat application where I want to load only N number of messages at first (say 20) and as the user scrolls up and reaches the top then more 20 messages are fetched via AJAX and prepended to the existing messages. These messages are older messages, of course. I searched everywhere for the logic to create an infinite scroll for reverse fetching rows from table and prepending but everywhere I got the infinite scroll to fetch and append the next rows which I do not want in this case. Therefore, I decided to try and create a logic or figure a way that I can do this reverse infinite scrolling myself. Hence, I tried doing the below thing.

What I tried: When the first 20 messages are fetched and say their id are in range 81-100 then I capture the lower id 81 and place it as in the data-id attribute of the parent container of the chat box. Now, when scroll event is called I send this id which is 81 to the backend and run the query with WHERE (id < 81 AND id >= 81-20) ORDER BY id ASC and return the earlier 20 rows as required. In the success function of the AJAX call I update the new lower id to the parent element of the chatbox. Where earlier it was 81 now it would be 61.

Problem: For the first scroll I can get the 81 detected properly but once the value changes the scroll element doesn’t detect the updated value which is 61. It still returns 81.

Expectations: How can I make the scroll event detect the updated data-id value whenever it user scrolls to the top?

Code

var chatBox = $(".retrive-chat");

$('.chat-box').scroll(function (event) {
  var st = $(this).scrollTop();
  var lastid = $(this).find(".retrive-chat").data('id');

  console.log(lastid); // RETURNS OLD VALUE EVERYTIME
  // PREPEND OLD MESSAGES IN CHAT ON SCROLL TOP
  if(st <= 10){
    $.ajax({
      url: 'processes/chat.php',
      type: 'POST',
      data: 'type=loadmore&to='+to+'&lastid='+lastid,
      dataType: 'JSON',
      success: function(data){
        chatBox.attr('data-id', data.mid); // UPDATE VALUE WHEN THE NEWS ROWS ARE FETCHED
        chatBox.prepend(data.html);
      }
    });
  }
});

HTML

<div class="retrive-chat" data-id="81"></div>

This data-id value is initially assigned from another AJAX call and then later updated when the scroll event gets fired but the updated value is not detected when the scroll event is fired again. It keeps on using 81.

2

Answers


  1. This is a problem that I’ve faced sometime too and the solution is very simple: be consistent.

    This happens if you modify the attribute with .data() but then want to read the value with .attr(). Use either one but don’t mix them:

    var chatBox = $(".retrive-chat");
    
    $('.chat-box').scroll(function (event) {
      var st = $(this).scrollTop();
      var lastid = $(this).find(".retrive-chat").attr('data-id');
    
      console.log(lastid); // RETURNS OLD VALUE EVERYTIME
      // PREPEND OLD MESSAGES IN CHAT ON SCROLL TOP
      if(st <= 10){
        $.ajax({
          url: 'processes/chat.php',
          type: 'POST',
          data: 'type=loadmore&to='+to+'&lastid='+lastid,
          dataType: 'JSON',
          success: function(data){
            chatBox.attr('data-id', data.mid); // UPDATE VALUE WHEN THE NEWS ROWS ARE FETCHED
            chatBox.prepend(data.html);
          }
        });
      }
    });
    

    OR:

    var chatBox = $(".retrive-chat");
    
    $('.chat-box').scroll(function (event) {
      var st = $(this).scrollTop();
      var lastid = $(this).find(".retrive-chat").data('id');
    
      console.log(lastid); // RETURNS OLD VALUE EVERYTIME
      // PREPEND OLD MESSAGES IN CHAT ON SCROLL TOP
      if(st <= 10){
        $.ajax({
          url: 'processes/chat.php',
          type: 'POST',
          data: 'type=loadmore&to='+to+'&lastid='+lastid,
          dataType: 'JSON',
          success: function(data){
            chatBox.data('id', data.mid); // UPDATE VALUE WHEN THE NEWS ROWS ARE FETCHED
            chatBox.prepend(data.html);
          }
        });
      }
    });
    

    You will notice this if you check the html in the inspector: Changing it with .data() the change will not be visible. Doing so with .attr() and the value will visibly change.

    Login or Signup to reply.
  2. Don’t use .attr() to update the id value, use .data():

    chatBox.data("id", data.mid);
    

    As is documented for jQuery’s .data() mechanism, the attribute values involved are read once. Thereafter, the values are maintained in an internal data structure by jQuery code, and the DOM attribute values are not changed.

    Note that as when you fetch the "id" value originally, you use just "id" to set it, not "data-id".

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search