AJAX load and page scrolling - javascript

I need help with the following problem. There is a button on my page and the press of the button loads content in a “div” element positioned below the button via AJAX. Everything works fine but one thing. The page scrolls a bit with each press of the button but I want it to keep its position.
Here is my HTML code:
<input type="button" name="calculate" value="Calculate"
onclick="invoke(this.form, this.name, '#result')"/>
And here is my JavaScript code (I am using jQuery):
function invoke(form, event, container) {
$('input[type="button"]').attr('disabled', 'disabled');
$(container).html('<br/><div class="img"><img src="/Test/img/ajax-loader.gif"/><div>');
$(container).load(form.action, event + '&' + $(form).serialize());
}
I searched through other posts but didn’t find any working solution. Any suggestions would be appreciated!

I found out where the problem came from. Since the content loaded in the “div” element changed its height 2 times with each press of the button, the height of the page body changed as well. This was the cause of the scrolling. I fixed the height of the “div” element in the css file:
div#result {height: 200px;}
This solved the problem.

Good, for the answer and also good if you give your code in jsfiddle. Still no issue, recently I have done the same thing.
By default it same position if you click on button, but if you have anchor tag, then it will automatically goes on top.
There is so many things to stay or scroll on desired position.
window.scrollTo(0, 0);
function buttonclick(isfirsttimeload)
{
if (typeof isfirsttimeload!= "undefined")
window.scrollTo(0, 0);
else
location.hash = '#asearchresult'; //this is hidden anchortag's id, which scrolldown on click.
}
http://www.w3schools.com/jsref/prop_loc_hash.asp
Using window.location.hash in jQuery

You have to call this function on page load.
limit – The number of records to display per request.
offset – The starting pointer of the data.
busy – Check if current request is going on or not.
The main trick for this scroll down pagination is binding the window scroll event and checking with the data container height
$(document).ready(function() {
$(window).scroll(function() {
// make sure u give the container id of the data to be loaded in.
if ($(window).scrollTop() + $(window).height() > $("#results").height() && !busy) {
busy = true;
offset = limit + offset;
displayRecords(limit, offset);
}
});
})
<script type="text/javascript">
var limit = 10
var offset = 0;
function displayRecords(lim, off) {
$.ajax({
type: "GET",
async: false,
url: "getrecords.php",
data: "limit=" + lim + "&offset=" + off,
cache: false,
beforeSend: function() {
$("#loader_message").html("").hide();
$('#loader_image').show();
},
success: function(html) {
$('#loader_image').hide();
$("#results").append(html);
if (html == "") {
$("#loader_message").html('<button data-atr="nodata" class="btn btn-default" type="button">No more records.</button>').show()
} else {
$("#loader_message").html('<button class="btn btn-default" type="button">Load more data</button>').show();
}
}
});
}
$(document).ready(function() {
// start to load the first set of data
displayRecords(limit, offset);
$('#loader_message').click(function() {
// if it has no more records no need to fire ajax request
var d = $('#loader_message').find("button").attr("data-atr");
if (d != "nodata") {
offset = limit + offset;
displayRecords(limit, offset);
}
});
});
</script>
Implementing with php ie getrecords.php
<?php
require_once("config.php");
$limit = (intval($_GET['limit']) != 0 ) ? $_GET['limit'] : 10;
$offset = (intval($_GET['offset']) != 0 ) ? $_GET['offset'] : 0;
$sql = "SELECT countries_name FROM countries WHERE 1 ORDER BY countries_name ASC LIMIT $limit OFFSET $offset";
try {
$stmt = $DB->prepare($sql);
$stmt->execute();
$results = $stmt->fetchAll();
} catch (Exception $ex) {
echo $ex->getMessage();
}
if (count($results) > 0) {
foreach ($results as $res) {
echo '<h3>' . $res['countries_name'] . '</h3>';
}
}
?>

Related

How can I make this button get clicked on scroll down for infinite scroll?

Here the button loads data from database. Works fine.
<li class="getmore" id="'.$post_id.'"><a>Load More Posts</a></li>
How can I make this button to get clicked automatically on scroll down to the bottom of the page . simply the infinite scroll.
should i use window scroll function .If yes then how can do it in this code.
I have tried by pasting the ajax code inside this function but not working.
Edit :
1. when I put the Ajax inside scroll function,It shows mysql error in getmore.php.
2. if I put the button class with click function inside scrolling function then it fires too fast that loads the same posts multiple times.
$(document).scroll(function(){
if ($(window).scrollTop() + $(window).height() >= $(document).height()) {
}
});
$('body').on('click','.getmore',function(){
var lastelement = $(this ).attr('id');
$.ajax({
type : 'GET',
url : 'getmore.php',
data : 'lastelement='+lastelement,
beforesend : function(){
$('.getmore').html('loading....');
},
success: function(data){
$('.getmore').remove();
$('#recs') .append(data) ;
}
});
});
<?php
$lastelement = $_REQUEST['lastelement' ];
include("connect2.php");
if ($lastelement!=''){
$query = "SELECT * FROM `posts` "
. "WHERE (id < " . $lastelement . " AND "
. "post_keywords like '%home%') "
. "ORDER BY `posts`.`id` DESC "
. "LIMIT 10";
$records = mysql_query($query);
if (mysql_num_rows($records)) {
while($record = mysql_fetch_array($records)){
$cookie_name = 'tcVotingSystem'.$record['id'];
$post_title = $record['post_title'];
$post_id = $record['id'];
$post_date = $record['post_date'];
$post_author = $record['post_author'];
$post_image = $record['post_image'];
$post_image2 = $record['post_image2'];
$post_keywords = $record['post_keywords'];
$post_content = substr($record['post_content'],0,100);
?>
<div>
//posts goes here
</div>
What you want to do is fire off the same Ajax request your button down once the scroll reaches a certain point. So instead of inserting the click event function on scroll, rather fire off your Ajax event
Example:
$(document).scroll(function(){
if ($(window).scrollTop() + $(window).height() >= $(document).height()) {
$.ajax({
type: 'GET',
url: 'getmore.php',
data:'lastelement='+lastelement,
beforesend: function(){
$('.getmore').html('loading....');
},
success: function(data){
$('.getmore').remove();
$('#recs') .append(data) ;
}
});
}
});
The above is just an example. As an aside, I would recommend that you create a function for your lazy loading ajax call as you may need to use it more than once i.e On click and scroll.
Hope this helps
To avoid multiple load during fast scroll you can go for this simple approach:
var isLoadingNewPage = false; //initializing the flag
$(document).scroll(function(){
if ($(window).scrollTop() + $(window).height() >= $(document).height())
{
if(!isLoadingNewPage)
{
$('.getmore').click(); //go for next page load
}
}
$('body').on('click','.getmore',function(){
//if the ajax request is going on then don't make another request; simply return back
if(isLoadingNewPage)
return;
var lastelement = $(this ).attr('id');
$.ajax({
type: 'GET',
url: 'getmore.php',
data:'lastelement='+lastelement,
beforesend: function(){
$('.getmore').html('loading....');
isLoadingNewPage = true; //setting the flag so that no more call needed till the time response comes back
},
success: function(data){
$('.getmore').remove();
$('#recs') .append(data) ;
isLoadingNewPage = false; //resetting the flag so that ajax can happen again if user scroll again
}
});
});
});
another approach can be this, put a button at the end of page, so while scrolling you can check if the button is entering in viewport and trigger the click
To avoid to show the same posts everytimes change the getmore ID with the last ID retrieved from ajax call
$.fn.isInViewport = function () {
var elementTop = $(this).offset().top;
var elementBottom = elementTop + $(this).outerHeight();
var viewportTop = $(window).scrollTop();
var viewportBottom = viewportTop + $(window).height();
return elementBottom > viewportTop && elementTop < viewportBottom;
};
if ($('.getmore').isInViewport()) {
$('.getmore').click();
}
$(window).scroll(function(){
if ($('.getmore').isInViewport()) {
$('.getmore').click();
}
$('body').on('click','.getmore',function(){
var lastelement = $(this ).attr('id');
$.ajax({
type : 'GET',
url : 'getmore.php',
data : 'lastelement='+lastelement,
beforesend : function(){
$('.getmore').html('loading....');
},
success: function(data){
/*
to avoid to show the same posts everytimes
change the getmore ID with the last ID retrieved from ajax call
*/
$('.getmore').attr('id', (lastelement + $('.getmore').attr('id')));
$('#recs') .append(data) ;
}
});
});
});
when your ajax response will be empty than you can remove the .getmore button
Such as suggested in other answer introduce a isLoadingNewPage variable is a good practice

How to make the ajax load on the scroll to about 90% instead of scrollbar reaching the bottom?

Here is the code sample and I its working all perfectly just the case is it loads further ajax request when the scroll bar hits the bottom, I want to make it load when it may reach upto 90% and beyond that form top.
$count = sql::read("SELECT COUNT(table_column_name) as count FROM table_name WHERE Info ='".$info."'");
$actual_row_count = $count[0]->count;
<script type="text/javascript">
$(document).ready(function(e) {
var page = 1;
var flag = 0;
$(window).scroll(function () {
$('#more').hide();
$('#no-more').hide();
if($(window).scrollTop() + $(window).height() > $(document).height() - 200) {
$('#more').css("top","400");
if(flag == 0)
{
$('#more').show();
}
}
if($(window).scrollTop() + $(window).height() == $(document).height()) {
$('#more').hide();
$('#no-more').hide();
page++;
var data = {
page_num: page,
info : '<?php echo $info; ?>'
};
var actual_count = "<?php echo $actual_row_count; ?>";
if((page-1)* 12 > actual_count){
$('#no-more').css("top","400");
$('#no-more').show();
flag = 1 ;
}
else{
$.ajax({
type: "POST",
url: "data.php",
data:data,
success: function(res) {
$("#result").append(res);
console.log(res);
}
});
}
}
});
});
</script>
What you need is to calculate if bottom of current viewport beyond 9/10 of total document height or not. Consider following expression, it might help:
($(window).scrollTop() + $(window).height()) / $(document).height() > 0.9
However, you main problem caused by the fact that scroll event fires multiple time per second. Therefore it make all possible calls before single ajax request has been resolved. You need to unattach event handler before making first call and reattach it after ajax succeed.
For example:
var win = $(window);
function onScroll() {
...
if (90% document scrolled) {
win.off('scroll', onScroll);
$.ajax({
...
success: function(res) {
$("#result").append(res);
win.on('scroll', onScroll);
}
});
}
}
win.on('scroll', onScroll);

Stop a div from showing with jquery

I have a load more button that appears once the user hits the bottom of the screen / fades out when scrolling up. Like so:
$(window).bind("scroll", function() {
if ($(document).height() <= ($(window).height() + $(window).scrollTop())) {
$("#loadmorebuilds-div").fadeIn();
} else {
$("#loadmorebuilds-div").fadeOut();
}
});
Here is what I use for loading the new content:
$(document).ready(function(){
var pageIndex = 1;
$('#loadmorebuilds-div').click(function() {
$('#buildcontainer').imagesLoaded( function(){
$.ajax({
url: 'includes/loadmorebuilds.php?type=follow&pageIndex=' + pageIndex,
success: function(html) {
var el = jQuery(html);
jQuery("#buildcontainer").append(el).masonry( 'reload' );
$("#loadmorebuilds-div").stop().fadeOut();
pageIndex++;
$("#buildcontainer").masonry()
rowCount = $('#countvar').length;
if (rowCount < 8) {
window.location.replace("http://localhost/buildsanctuary/index.php");
}
}
});
});
});
});
And this part here, checks the amount of returned data and if its less than requested, it means that there is no more data to show.
rowCount = $('#countvar').length;
if (rowCount < 8) {
window.location.replace("http://localhost/buildsanctuary/index.php");
}
The page re-direct is just to test that it was working, what I want is to instead not allow the page to show the load more button again.
How can I go about this?
I tried changing the class e.g.
$("#loadmorebuilds-div").attr("class", "loadmorebuild-divhidden");
But that doesn't work, the hidden class is just display:none.
Thanks.
Sorted this by removing it from the dom with
.remove()
Not sure why i didn't think of this!

Run jquery function again after ajax call

Is there any way to run a script again after an ajax call?
I have a photoswipe (lightbox) jquery plug-in I call like this:
jQuery(document).ready(function($){
if( $('.img-frame a').length > 0 ){
var myPhotoSwipe = $(".img-frame a").photoSwipe();
}
});
I also have an ajax 'load more posts' function, and obviously photoswipe doesn't target images loaded after the first page load.
I don't have much ajax knowledge, any help on this? Thanks
UPDATE: Here's the 'load more' script:
jQuery(document).ready(function($) {
// The number of the next page to load (/page/x/).
var pageNum = parseInt(djwd_load_posts.startPage) + 1;
// The maximum number of pages the current query can return.
var max = parseInt(djwd_load_posts.maxPages);
// The link of the next page of posts.
var nextLink = djwd_load_posts.nextLink;
/**
* Replace the traditional navigation with our own,
* but only if there is at least one page of new posts to load.
*/
if(pageNum <= max) {
// Insert the "More Posts" link.
$('#content')
.append('<div class="lp-placeholder-'+ pageNum +'"></div>')
.append('<p id="lp-load-posts" class="long-button">Load More Posts<i class="icon-chevron-down icon-large"></i></p>');
// Remove the traditional navigation.
$('#nav-below').remove();
}
/**
* Load new posts when the link is clicked.
*/
$('#lp-load-posts a').click(function() {
// Are there more posts to load?
if(pageNum <= max) {
// Show that we're working.
$(this).text('Loading posts...');
$('.lp-placeholder-'+ pageNum).load(nextLink + ' .post',
function() {
$( this ).hide().fadeIn(700);
// Update page number and nextLink.
pageNum++;
nextLink = nextLink.replace(/\/page\/[0-9]?/, '/page/'+ pageNum);
// Add a new placeholder, for when user clicks again.
$('#lp-load-posts')
.before('<div class="lp-placeholder-'+ pageNum +'"></div>')
// Update the button message.
if(pageNum <= max) {
$('#lp-load-posts a').text('Load More Posts');
} else {
$('#lp-load-posts a').text('No more posts to load.');
}
}
);
} else {
$('#lp-load-posts a').append('.');
}
return false;
});
});
I call it in Wordpress functions.php this way:
function djwd_ajax_load_init() {
global $wp_query;
if( !is_singular() ) {
wp_enqueue_script('ajax-load-posts', get_template_directory_uri() . '/js/ajax-load-posts.js', array('jquery'), true );
$max = $wp_query->max_num_pages;
$paged = ( get_query_var('paged') > 1 ) ? get_query_var('paged') : 1;
wp_localize_script(
'ajax-load-posts',
'djwd_load_posts',
array(
'startPage' => $paged,
'maxPages' => $max,
'nextLink' => next_posts($max, false)
)
);
}
}
add_action('template_redirect', 'djwd_ajax_load_init');
Put it in a function, call in on pageload and in your ajax call.
function setMyPhotoSwipe() {
var $targets = $('.img-frame a').not('.photo-swipe');
if($targets.length > 0 ){
$targets.addClass('photo-swipe').photoSwipe();
};
};
jQuery(document).ready(function($){
setMyPhotoSwipe();
});
By the way, if dont't need variable myPhotoSwipe, then you dont't have to set it. You are also using $('.img-frame a') twice, so cache the result.
And your load call:
$('.lp-placeholder-'+ pageNum).load(nextLink + ' .post',
function() {
$( this ).hide().fadeIn(700);
// Update page number and nextLink.
pageNum++;
nextLink = nextLink.replace(/\/page\/[0-9]?/, '/page/'+ pageNum);
// Add a new placeholder, for when user clicks again.
$('#lp-load-posts')
.before('<div class="lp-placeholder-'+ pageNum +'"></div>')
// Update the button message.
if(pageNum <= max) {
$('#lp-load-posts a').text('Load More Posts');
} else {
$('#lp-load-posts a').text('No more posts to load.');
}
// New content has been loaded and insertet, so set up photo swipe
setMyPhotoSwipe();
}
);
There is no delegation for plugin, its up to author's plugin to incorporate it. Why not cheating: (sorry, cannot test code and not sure its relevant to photoSwipe plugin)
jQuery(document).ready(function($){
$(this).on('mousedown','.img-frame a',function(){ //document or better parent container// mousedown or any relevent event use by photoSwipe
if(!$(this).data('swiped')) {
$(this).data('swiped',true).photoSwipe();
}
});
});
$.ajax({
url: 'url/test.php',
success: function(data) { // also gets response from php and can be manipulated if required!
setMyPhotoSwipe();
}
});
I would suggest the below
jQuery(document).ready(InitializeSettings);
also call the same in ajax calls
ajax_success_function(){ // depends on your ajax call
InitializeSettings();
}
function InitializeSettings(){
if( $('.img-frame a').length > 0 ){
var myPhotoSwipe = $(".img-frame a").photoSwipe();
}
}
Like Morpheus said.
Create a seperate function that put your code in that.
You can call that function inside your $(document).ready()
Then use that same function in your ajax success path (check documentation: http://api.jquery.com/jQuery.ajax/).
Alternatively you can use this: http://api.jquery.com/ajaxStop/
It will facilitate you to use the same function when your every Ajax Call stops.
Sorry I'm a novice in jquery... How about using ajaxComplete()
http://api.jquery.com/ajaxcomplete/
Once I had to execute a function after ajax call... and ajaxComplete() did the trick...
$(document).ready(function(){
function some_function()
{
//---- this function to be called after ajax request...
}
$( document ).ajaxComplete(function() {
some_function();
});
})

Replace scrolling action by onclick

I used this snippet of code (had to adapt it) to autoload (think Twitter) new posts on my page when scrolling.
Since this is resource heavy for my server when a user scrolls fast, I want it to be activated when clicking on a button, lets say <button id="load_more">Load more</button>
Can anyone help me convert mine ? I can't get it to work... (plus eventually remove the busy indicator)
Here is the code I use for autoscroll :
<?php
$maxPage = $this->Paginator->counter('%pages%');
?>
<script type="text/javascript">
var lastX = 0;
var currentX = 0;
var page = 1;
$(window).scroll(function () {
if (page < <?php echo $maxPage;?>) {
currentX = $(window).scrollTop();
if (currentX - lastX > 150 * page) {
lastX = currentX - 150;
page++;
$("#busy-indicator").fadeIn();
$.get('<?php echo $this->Html->url('/users/getmore_timeline/'.$this->Session->read('Auth.User.id')); ?>/page:' + page, function(data) {
setTimeout(function(){
$('#postList').append(data);
var bi = $("#busy-indicator");
bi.stop(true, true);
bi.fadeOut();
}, 500);
});
}
}
});
</script>
EDIT :
I tried (from memory)
<button onlick"LoadMore()">Load More</button>
<?php
$maxPage = $this->Paginator->counter('%pages%');
?>
<script type="text/javascript">
function LoadMore () {
if (page < <?php echo $maxPage;?>) {
page++;
$("#busy-indicator").fadeIn();
$.get('<?php echo $this->Html- >url('/users/getmore_timeline/'.$this->Session->read('Auth.User.id')); ?>/page:' + page, function(data) {
setTimeout(function(){
$('#postList').append(data);
var bi = $("#busy-indicator");
bi.stop(true, true);
bi.fadeOut();
}, 500);
});
}
};
</script>
i'm not sure if i missed something here, but if all you want is a button to call the function LoadMore():
HTML
<button id="load_more">Load more</button>
JS
$('#load_more').on('click', function() {
Loadmore()
})
PS: about your <button onlick"LoadMore()">Load More</button>, you have a typo (very funny one :D), forgot a equal sign, and you should avoid using inline event handlers.

Categories