I have a recursive function that populates a list until the bottom of the screen is reached, then stops.
Each time the recursive function is called, the "start" global variable increments by the limit (5). For example, after 3 times, the "start" variable should be 15. This shows up correctly in the console.
However, outside the recursive function, it seems the "start" variable is still at "0". I thought using "var start = 0" outside of the function makes it global and should be changed by the Ajax success function. The code is below:
//****************************************************************
// Loading questions and answers listings
//****************************************************************
var tag = '';//initialize as blank
var search = '';//initialize as blank
var limit = 5;//number of records to autoload each time
var start = 0;//start at record 0
var action = 'inactive';//initial status to get initial load
var autoscroll = 'false';//check box to engage auto scroll or keep manual load more
var checked = '';//check box value for autoscroll
function load_data(limit, start, search, tag){//recursive function for auto loading
search = $('#search').val();
var loads;
$.ajax({
url:"/modules/posts/questions_all_autoscroll_fetchdata.php",
method:"POST",
data:{limit:limit, start:start, search:search, tag:tag},
cache:false,
success:function(data){
$('#load_data_message').show();//bring loading button back once load successful.
//It is removed during tag click search to avoid glitchy appearance of button showing at top left briefly.
$('#load_data').append(data);
//checks if quantity "limit" amount loaded. If not, that means end of data reached.
//Each data piece has id="container", so counting them tells how many data pieces returned in "loads"
loads = $(data).find('.card-header').length;
if(loads<limit){button_name = 'End of Data';}else{button_name='Loading More <i class="fas fa-spinner fa-lg fa-spin"></i>';}
if(autoscroll == 'false'){button_name = 'Load More'};
//append data returned to bottom of existing data
$('#load_data_message').html("<div id='please_wait' class='form-row text-center'>\
<div class='col-12'><button type='button' class='btn btn-warning'>\
"+button_name+"</button>\
<label style='cursor:pointer;'><input id='autoscroll' type='checkbox' name='autoscroll' value='true' "+checked+"\
style='transform:scale(2.0);margin-left:10px;margin-top:15px;cursor:pointer;'> Autoscroll</label><br></div></div>");
action = "inactive";
//recursive part - keep loading data until bottom of screen reached, stop when reached, or when end of data
start = start + limit;
console.log(start);
if(loads>=limit){
if($("#load_data").height() < $(window).height()){load_data(limit,start,search,tag);}
}
}
});
}
I do an initial load of the listing on page load with:
//for initial loading of data to the bottom of page (through recursive load_data function
if(action == 'inactive') {
action = 'active';
load_data(limit, start,search, tag);
}
Then if I want to initiate an auto/infinite scroll, I click the checkbox which initiates the code below. However, the "start" value is "0", where it should have been affected by the Ajax recursive function previously, and start at "15" instead. I get a repeat of previously posted data, which is not wanted.
//auto scroll checkbox clicked, putting into autoload/autoscroll mode
$(document).on("change", "#autoscroll", function(){
autoscroll = this.checked;
if(autoscroll == true){checked = 'checked';}else{checked = '';}
console.log(start);
load_data(limit, start, search, tag);
});
Then auto/infinite scroll works as follows. The "start" variable is continually updated successfully, but probably within the loop, rather than the recursive Ajax part.
//autoload portion. when scrolling reaches bottom of screen, triggers another load of data
$(window).scroll(function(){
if(autoscroll == true){
if($(window).scrollTop() + $(window).height() > $("#load_data").height() && action == 'inactive' && button_name != 'End of Data'){
action = 'active';
start = start + limit;
//load_data(limit, start, search, tag);
setTimeout(function(){
load_data(limit, start, search, tag);
}, 500);
console.log('scroll function called!');
}
}
});
Bottom line question - I would like to use the global variable "start" and have it changed by the recursive function's Ajax success function. How can this be achieved?
The "loads = $(data).find('.card-header').length" does count the number of class='card-header' instances, contrary to what user2137480 has mentioned above, and everything does increment properly. The issue was that the "start" variable outside the Ajax success function was not being updated as the "load_data" function was called recursively.
Found a clumsy way to make this work. I used a session storage variable, "sessionStorage.start" that gets affected within the Ajax success function, even at recursive levels. Seems like session variables scopes are truly "global"! Then this sessionStorage.start variable is use elsewhere in the code to update the global "start" variable. This value is then maintained consistently throughout the code. Just have to remember that the session variables are text and must be converted to numbers (for this application anyways). See below if you are interested:
//****************************************************************
// Loading questions and answers listings
//****************************************************************
var limit = 5;//number of records to autoload each time
sessionStorage.start = 0;
var start = 0;//start at record 0
sessionStorage.start = start;
sessionStorage.scroll_function_enable = 'false';
var action = 'inactive';//initial status to get initial load
var autoscroll = 'false';//check box to engage auto scroll or keep manual load more
var checked = '';//check box value for autoscroll
function load_data(limit, start, search, tag){//recursive function for auto loading
console.log('load data begin');
console.log('recursive start: ' + start);
sessionStorage.scroll_function_enable = 'false';
search = $('#search').val();
var loads;
$.ajax({
url:"/modules/posts/questions_all_autoscroll_fetchdata.php",
method:"POST",
data:{limit:limit, start:start, search:search, tag:tag},
cache:false,
success:function(data){
$('#load_data_message').show();//bring loading button back once load successful.
//It is removed during tag click search to avoid glitchy appearance of button showing at top left briefly.
$('#load_data').append(data);
//checks if quantity "limit" amount loaded. If not, that means end of data reached.
//Each data piece has id="container", so counting them tells how many data pieces returned in "loads"
loads = $(data).find('.card-header').length;
//alert(loads);
if(loads<limit){button_name = 'End of Data';}else{button_name='Loading More <i class="fas fa-spinner fa-lg fa-spin"></i>';}
if(autoscroll == 'false'){button_name = 'Load More'};
//append data returned to bottom of existing data
$('#load_data_message').html("<div id='please_wait' class='form-row text-center'>\
<div class='col-12'><button id='load_button' type='button' class='btn btn-warning'>\
"+button_name+"</button>\
<label style='cursor:pointer;'><input id='autoscroll' type='checkbox' name='autoscroll' value='true' "+checked+"\
style='transform:scale(2.0);margin-left:10px;margin-top:15px;cursor:pointer;'> Autoscroll</label><br></div></div>");
action = "inactive";
//recursive part - keep loading data until bottom of screen reached, stop when reached, or when end of data
start = start + limit;
sessionStorage.start = start;//needed because recursive routine does not update the global "start" variable. Needed to pass value outside of recursive routine
console.log('recursive end: '+start);
if(loads>=limit){
if($("#load_data").height() < $(window).height())
{
load_data(limit,start,search,tag);
}else
sessionStorage.scroll_function_enable = 'true';
}
}
});
}
//for initial loading of data to the bottom of page (through recursive load_data function
if(action == 'inactive') {
action = 'active';
load_data(limit, start,search, tag);
start = Number(sessionStorage.start);//to get recursive value of start, otherwise will not retain its value
}
//auto scroll checkbox clicked, putting into autoload/autoscroll mode
$(document).on("change", "#autoscroll", function(){
autoscroll = this.checked;
if(autoscroll == true){checked = 'checked';}else{checked = '';}
start = Number(sessionStorage.start);//to get recursive value of start, otherwise will not retain its value
console.log('autoscroll start: ' + start);
load_data(limit, start, search, tag);
start = Number(sessionStorage.start);//to get recursive value of start, otherwise will not retain its value
});
//autoload portion. when scrolling reaches bottom of screen, triggers another load of data
$(window).scroll(function(){
if(autoscroll == true){
if($(window).scrollTop() + $(window).height() > $("#load_data").height() && action == 'inactive' && button_name != 'End of Data' && sessionStorage.scroll_function_enable == 'true'){
action = 'active';
start = Number(sessionStorage.start);//to get number where other processes have left off
console.log('scroll start: ' + start);
//load_data(limit, start, search, tag);
setTimeout(function(){
load_data(limit, start, search, tag);
}, 500);
start = Number(sessionStorage.start);//to get recursive value of start, otherwise will not retain its value
}
}
});