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 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.
CodePudding user response:
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.
CodePudding user response:
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".