Infinite Scroll with MySQL Data - php

I have followed help located in this topic: Using infinite scroll w/ a MySQL Database
And have gotten close to getting this working properly. I have a page that is displayed in blocks using jquery masonry, in which the blocks are populated by data from a mysql database. When I scroll to the end of the page I successfully get the loading.gif image but immediately after the image it says "No more posts to show." which is what it should say if that were true. I am only calling in 5 posts initially out of about 10-15, so the rest of the posts should load when I reach the bottom of the page but I get the message that is supposed to come up when there really aren't any more posts.
Here is my javascript:
var loading = false;
$(window).scroll(function(){
if($(window).scrollTop() == $(document).height() - $(window).height()) {
var h = $('.blockContainer').height();
var st = $(window).scrollTop();
var trigger = h - 250;
if((st >= 0.2*h) && (!loading) && (h > 500)){
loading = true;
$('div#ajaxLoader').html('<img src="images/loading.gif" name="HireStarts Loading" title="HireStarts Loading" />');
$('div#ajaxLoader').show();
$.ajax({
url: "blocks.php?lastid=" + $(".masonryBlock:last").attr("id"),
success: function(html){
if(html){
$(".blockContainer").append(html);
$('div#ajaxLoader').hide();
}else{
$('div#ajaxLoader').html('<center><b>No more posts to show.</b></center>');
}
}
});
}
}
});
Here is the php on the page the blocks are actually on. This page initially posts 5 items from the database. The javascript grabs the last posted id and sends that via ajax to the blocks.php script, which then uses the last posted id to grab the rest of the items from the database.
$allPosts = $link->query("/*qc=on*/SELECT * FROM all_posts ORDER BY post_id DESC LIMIT 5");
while($allRows = mysqli_fetch_assoc($allPosts)) {
$postID = $link->real_escape_string(intval($allRows['post_id']));
$isBlog = $link->real_escape_string(intval($allRows['blog']));
$isJob = $link->real_escape_string(intval($allRows['job']));
$isVid = $link->real_escape_string(intval($allRows['video']));
$itemID = $link->real_escape_string(intval($allRows['item_id']));
if($isBlog === '1') {
$query = "SELECT * FROM blogs WHERE blog_id = '".$itemID."' ORDER BY blog_id DESC";
$result = $link->query($query);
while($blogRow = mysqli_fetch_assoc($result)) {
$blogID = $link->real_escape_string($blogRow['blog_id']);
$blogTitle = $link->real_escape_string(html_entity_decode($blogRow['blog_title']));
$blogDate = $blogRow['pub_date'];
$blogPhoto = $link->real_escape_string($blogRow['image']);
$blogAuthor = $link->real_escape_string($blowRow['author']);
$blogContent = $link->real_escape_string($blogRow['content']);
//clean up the text
$blogTitle = stripslashes($blogTitle);
$blogContent = html_entity_decode(stripslashes(truncate($blogContent, 150)));
echo "<div class='masonryBlock' id='".$postID."'>";
echo "<a href='post.php?id=".$blogID."'>";
echo "<div class='imgholder'><img src='uploads/blogs/photos/".$blogPhoto."'></div>";
echo "<strong>".$blogTitle."</strong>";
echo "<p>".$blogContent."</p>";
echo "</a>";
echo "</div>";
}
}
Here is the php from the blocks.php script that the AJAX calls:
//if there is a query in the URL
if(isset($_GET['lastid'])) {
//get the starting ID from the URL
$startID = $link->real_escape_string(intval($_GET['lastid']));
//make the query, querying 25 fields per run
$result = $link->query("SELECT * FROM all_posts ORDER BY post_id DESC LIMIT '".$startID."', 25");
$html = '';
//put the table rows into variables
while($allRows = mysqli_fetch_assoc($result)) {
$postID = $link->real_escape_string(intval($allRows['post_id']));
$isBlog = $link->real_escape_string(intval($allRows['blog']));
$isJob = $link->real_escape_string(intval($allRows['job']));
$isVid = $link->real_escape_string(intval($allRows['video']));
$itemID = $link->real_escape_string(intval($allRows['item_id']));
//if the entry is a blog
if($isBlog === '1') {
$query = "SELECT * FROM blogs WHERE blog_id = '".$itemID."' ORDER BY blog_id DESC";
$result = $link->query($query);
while($blogRow = mysqli_fetch_assoc($result)) {
$blogID = $link->real_escape_string($blogRow['blog_id']);
$blogTitle = $link->real_escape_string(html_entity_decode($blogRow['blog_title']));
$blogDate = $blogRow['pub_date'];
$blogPhoto = $link->real_escape_string($blogRow['image']);
$blogAuthor = $link->real_escape_string($blowRow['author']);
$blogContent = $link->real_escape_string($blogRow['content']);
$blogTitle = stripslashes($blogTitle);
$blogContent = html_entity_decode(stripslashes(truncate($blogContent, 150)));
$html .="<div class='masonryBlock' id='".$postID."'>
<a href='post.php?id=".$blogID."'>
<div class='imgholder'><img src='uploads/blogs/photos/".$blogPhoto."'></div>
<strong>".$blogTitle."</strong>
<p>".$blogContent."</p>
</a></div>";
}
}
echo $html;
}
I have tried using the jquery infinite-scroll plugin, but it seemed much more difficult to do it that way. I don't know what the issue is here. I have added alerts and did testing and the javascript script is fully processing, so it must be with blocks.php right?
EDIT: I have made a temporary fix to this issue by changing the sql query to SELECT * FROM all_posts WHERE post_id < '".$startID."' ORDER BY post_id DESC LIMIT 15
The blocks are now loading via ajax, however they are only loading one block at a time. The ajax is sending a request for every single block and they are fading in one after another, is it possible to make them all fade in at once with jquery masonry?

I seen your code in another answer, and I would recommend using the LIMIT functionality in MySql instead of offsetting the values. Example:
SELECT * FROM all_posts ORDER BY post_id DESC LIMIT '".(((int)$page)*5)."',5
This will just take a page number in the AJAX request and get the offset automatically. It's one consistent query, and works independent of the last results on the page. Send something like page=1 or page=2 in your jQuery code. This can be done a couple different ways.
First, count the number of elements constructed on the page and divide by the number on the page. This will yield a page number.
Second, you can use jQuery and bind the current page number to the body:
$(body).data('page', 1)
Increment it by one each page load.
Doing this is really the better way to go, because it uses one query for all of the operations, and doesn't require a whole lot of information about the data already on the page.
Only thing to note is that this logic requires the first page request to be 0, not 1. This is because 1*5 will evaluate to 5, skipping the first 5 rows. If its 0, it will evaluate to 0*5 and skip the first 0 rows (since 0*5 is 0).
Let me know any questions you have!

Have you tried doing any debugging?
If you are not already using, I would recommend getting the firebug plugin.
Does the ajax call return empty? If it does, try echoing the sql and verify that is the correct statement and that all the variables contain the expected information. A lot of things could fail considering there's a lot of communication happening between client, server and db.
In response to your comment, you are adding the html in this piece of code:
if(html){
$(".blockContainer").append(html);
$('div#ajaxLoader').hide();
}
I would do a console.log(html) and console.log($(".blockContainer").length) before the if statement.

Related

Auto Refresh DIV contents from Mysql table - one at a time

I need to automatically refresh content from a mysql data table every 5 seconds, but showing only one distinct record at a time, going through every record in a endless loop.
I load news.php, that has this js :
<script type="text/javascript">
var auto_refresh = setInterval(function () {
$('#canvas').load('content.php').fadein("medium");}, 5000);
// refresh every 5 seconds
</script>
content.php has the db connection
$query_Recordset5 = "SELECT * FROM news";
$Recordset5 = mysql_query($query_Recordset5, $connection) or die(mysql_error());
$row_Recordset5 = mysql_fetch_assoc($Recordset5);
$totalRows_Recordset5 = mysql_num_rows($Recordset5);
As well as the fields echoed to the page.
I understand that you would have to create a counter and bring back one different record everytime, but I am having a tough time with it.
Thanks
If your table has an auto increment field (say "id"). You start by passing page.php and id of 0, so it will grab the auto increment field greater than 0, and then you pass that fields ID back through jquery. When you send it a second time it will not be included because you will be using the greater than sign.
The if num_rows == 0 checks to see if there are any fields, if none, then it will assume that the auto increment field you sent it is the last one, and then it will run the sql statement with the very first auto increment value.
<?php
// page.php
$id = (int) $_REQUEST['id'];
$sq = "select * from news where id > ".$id." order by id asc limit 0,1";
$qu = $con->query($sq);
if ($qu->num_rows == 0) {
$sq2 = "select * from news order by id asc limit 0,1";
$qu2 = $con->query($s2);
while ($fe = $qu->fetch_assoc()) {
echo $fe['id']."|".$fe['content'];
}
} else {
while ($fe = $qu->fetch_assoc()) {
echo $fe['id']."|".$fe['content'];
}
}
?>
<script>
$(document).ready(function() {
setInterval(function(){ updateNews(); }, 5000);
});
function updateNews() {
var id = 0;
id = $("#hidden-id").val();
$.get("page.php?id=" + id, function(data) {
// I use $.get so that I can split the data that it returns before populating
// the #canvas. This way we can strip off the first part which is the auto
// increment
var ref = data.split('|');
$("#hidden-id").val(ref[0]);
$("#canvas").html(ref[1]);
});
}
</script>

while loop output with delay

i am using while loop to display last 30 albums thumbnail but as you know 30 photo at once will slow down webpage loading time si i want once the webpage is completely loaded i want to load these 30 photo in interval of 5 seconds. first 5 photo will be loaded after 5 seconds of webpage is fully loaded then again after gap of 5 seconds next 5 photo will be loaded i know i can do this with 6 query but why to waste server resources so i want one query but loading as per users convenient.here is my while loop
$res = mysql_query("SELECT * from `"tableA where cat='photos' order by created desc limit 30");
while($row = mysql_fetch_array($res)) {
$photo .= thumbnail($row,150);
}
after that whereever i want i can call $photo
The best way to do this is with javascript (and jQuery for extra ease). Check out this Lazy Loading jQuery plugin for example.
You should output some markup that contains either the URLs of the images or data from which Javascript can recreate the URLs, and then, on the client side you may handle creating images from that markup on the fly, with delays and whatnot.
Try this.. I also fixed the quotes in your query a bit..
<?php
$round =1;
$res = mysql_query("SELECT * from `tableA` where `cat`='photos' order by created desc limit 30");
while($row = mysql_fetch_array($res))
{
$photo .= thumbnail($row,150);
if (($round % 5) == 0 ) { // action only happens when round is divisble by 5
sleep(5); // wait 5 seconds
}
$round += 1;
}
?>
In your case, the page is displayed to the user only AFTER all PHP were executed so you can't count on PHP to delay some display.
As already mentionned you'll have to do it client side (probably in Javascript).
A way would be to construct (using PHP) a Javascript array containing all your image URL and then loop through this array with appropriate delay.
The server side will look like this : (EDIT : assuming tableA contains a column named 'url')
$images = array();
$res = mysql_query("SELECT * from `tableA` where cat='photos' order by created desc limit 30");
while($row = mysql_fetch_array($res)) {
$images[] = $row['url'];
}
echo json_encode($images);

Only get new data from PHP file - jQuery

Instead of reloading old data from a PHP file that I parse with JavaScript using JSON, I want to ONLY load new data. My project is a little multiplayer environment and my goal is to have all users see either other move in realtime.
Here is my code:
JavaScript:
function getUsers() {
$.get("database/getData.php", function(data) {
// data returned from server;
for(var i = 0; i < data.response.length; i++) {
// users obtained from the array... parse them now
var user = data.response[i].split(" ");
// user info
var id = user[0];
var username = user[1];
var xx = user[2];
var yy = user[3];
userCount = data.response.length;
$(".online").html(userCount + " users online right now.")
// position the users
moveCharacter(username, xx, yy);
}
}, "json");
}
var infoGetter = setInterval(getUsers, 2000); // we may need to improve this... type of realtime
And here is my PHP:
<?
$database = sqlite_open("thenew.db", 0999, $error);
if(!$database) die($error);
$query = "SELECT * FROM users";
$results = sqlite_query($database, $query);
if(!$results) die("Canot execute query");
$data = array();
while($row = sqlite_fetch_array($results)) {
$data[] = $row['uid'] . " " . $row['username'] . " " . $row['xPos'] . " " . $row['yPos'];
}
echo json_encode(array("response"=>$data));
sqlite_close($database);
?>
How can I make it so ONLY new data from the PHP file is parsed by the JavaScript instead of all data?
Thanks!
I would suggest you to modify the select query. Instead of having it as select * from users, add some where condition like where userId > somenumber. Now send the last userId which we processed in the last request along with next request which you make from client side. This will make sure that you will always gets new response.
Indeed, with your current setup, every call to "getUsers" will replay the entire state of the game up to the last move made, and not necessarily finish in the correct state. In order to get the behavior you want, you will need to add a timestamp or serial id to the "users" table and then order your results in order to get the most recent moves. You will need to do this for each user separately, so you will also need to provide a mechanism to retrieve and iterate through all users...
Thus your javascript becomes something like...
function getUsers() {
$.get("database/getAllUsers.php", function(data) {
$.each(data, function(i,uid) {
$.get("database/getData.php?uid=".uid, function(data) {
...
and your php query becomes...
$query = "SELECT * FROM users WHERE uid=$_GET['uid'] ORDER BY timestamp DESC LIMIT 1

AJAX -> PHP not updating MySQL database consistently

So this is my early attempt at a Facemash style site in which the user will select one of two images, scoring a hit with the chosen image (the winner) and a miss with the unselected image (the loser) - both of which are recorded in a MySQL database.
The selected image is determined using javascript and uses jquery AJAX to notify a PHP script (backend.php) which updates the database.
This works absolutely correctly for updating the "hits" field. However, the "misses" are not consistently recorded. By this I mean that when the user clicks one image, the fact the other image has not been clicked is only sometimes shown in the database. As far as I can tell there is no pattern as to when the "miss" is and is not recorded, making it difficult to pinpoint where the problem lies.
I've checked the code over and over again and cannot understand why this is happening or what would be responsible for it, so I thought it would be best to post everything. I appreciate it's a lot to ask, but any explaination as to why I'm having this problem would be hugely appreciated, thanks.
<html>
<head>
<title>Facemash</title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.5.2/jquery.js"></script>
</head>
<body>
<?php
// Make a MySQL Connection
mysql_connect("localhost", "admin", "admin") or die(mysql_error());
mysql_select_db("facemash") or die(mysql_error());
// Select two random people
$personA = rand(1, 28);
$personB = rand(1, 28);
// Ensure that it is not the same person
if ($personB == $personA) {
$personB = rand(1, 28);
}
// Function to return path of photo
function photoPath ($person){
$query = mysql_query("SELECT photo FROM people WHERE id=$person");
$result = mysql_fetch_row($query);
$result = $result[0];
echo $result;
}
?>
<!--Image for personA-->
<div id=photoA identity="<?php echo $personA ?>"><img src="<?php photoPath($personA);?>"/></div>
<!--Image for personB-->
<div id=photoB identity="<?php echo $personB ?>"><img src="<?php photoPath($personB);?>"/></div>
<script type="text/javascript">
$('#photoA').click(function() {
var hit = $('#photoA[identity]').attr('identity');
var miss = $('#photoB[identity]').attr('identity');
$.post ("backend.php", {winner: hit} );
$.post ("backend.php", {loser: miss} );
location.reload(true);
});
$('#photoB').click(function() {
var hit = $('#photoB[identity]').attr('identity');
var miss = $('#photoA[identity]').attr('identity');
$.post ("backend.php", {winner: hit} );
$.post ("backend.php", {loser: miss} );
location.reload(true);
});
</script>
</body>
</html>
backend.php:
<?php
// Make a MySQL Connection
mysql_connect("localhost", "admin", "admin") or die(mysql_error());
mysql_select_db("facemash") or die(mysql_error());
// Recieve id of winner from index.php
$winner = $_POST['winner'];
// Recieve id of loser from index.php
$loser = $_POST['loser'];
// Lookup hits for winner and update by adding 1
function updateHits ($winner) {
$query = mysql_query("SELECT hits FROM people WHERE id=$winner");
$result = mysql_fetch_row($query);
$result = $result[0];
$result++;
mysql_query("UPDATE people SET hits = $result WHERE id=$winner");
}
//Lookup misses for loser and update by adding 1
function updateMisses ($loser) {
$query = mysql_query("SELECT misses FROM people WHERE id=$loser");
$result = mysql_fetch_row($query);
$result = $result[0];
$result++;
mysql_query("UPDATE people SET misses = $result WHERE id=$loser");
}
updateHits($winner);
updateMisses($loser);
?>
Thanks again.
Couple things.
// Select two random people
$personA = rand(1, 28);
$personB = rand(1, 28);
// Ensure that it is not the same person
if ($personB == $personA) {
$personB = rand(1, 28);
}
This doesn't look like it will always guarantee they aren't the same person. The result of the second rand() could again return the same value as $personA
Instead of doing two queries to first select the misses and then increment it, why not make it one query?:
mysql_query("UPDATE people SET misses = misses + 1 WHERE id=$loser");
Lastly, in backend.php, instead of updating winners and losers even if you have only received one of the params, do an if else:
if($winner) {
updateHits($winner);
} else if ($loser) {
updateMisses($loser);
}
I think this will solve your problems.
As a matter of optimization, you should also combine your two POSTs into one.
Try changing your two functions to this and seeing if it will work. (If it doesn't I will just delete my answer.)
// Lookup hits for winner and update by adding 1
function updateHits ($winner) {
mysql_query("UPDATE `people` SET `hits` = hits + 1 WHERE `id`= '$winner'");
}
//Lookup misses for loser and update by adding 1
function updateMisses ($loser) {
mysql_query("UPDATE `people` SET `misses` = misses + 1 WHERE `id` = '$loser'");
}
This probably doesn't cause the problem, but you should only do one $.post and don't duplicate the same functionality in both click handlers.
JS:
$('#photoA, #photoB').click(function() {
var hit = $('#photoA[identity]').attr('identity'),
miss = $('#photoB[identity]').attr('identity');
$.post("backend.php", { winner: hit, loser: miss } );
location.reload(true);
});

help with chained selects and existing form values, ex: adding <option selected="selected"></option>

I have a 3 step chained-select sequence, game -> battle -> winning side , which pulls all data from a MySQL database.
After some wandering on the internet, I found a compact jQuery script that performs wonderfully. However, I am at a loss as to how to allow for existing data: <option selected="selected"></option> using this script.
chained select javascript:
<script>
var ajax = new Array();
function getScenNumList(sel)
{
var game = sel.options[sel.selectedIndex].value;
document.getElementById('scenarioNumber').options.length = 0; // Empty scenario number select box
if(game.length>0){
var index = ajax.length;
ajax[index] = new sack();
ajax[index].requestFile = 'js/getPlayData.php?gameName='+game; // Specifying which file to get
ajax[index].onCompletion = function(){ createScenarioNumbers(index) }; // Specify function that will be executed after file has been found
ajax[index].runAJAX(); // Execute AJAX function
}
}
function createScenarioNumbers(index)
{
var obj = document.getElementById('scenarioNumber');
eval(ajax[index].response); // Executing the response from Ajax as Javascript code
}
function getNations(sel)
{
var scenNum = sel.options[sel.selectedIndex].value;
document.getElementById('victor').options.length = 0; // Empty nation select box
if(scenNum.length>0){
var index = ajax.length;
ajax[index] = new sack();
ajax[index].requestFile = 'js/getPlayData.php?scenID='+scenNum; // Specifying which file to get
ajax[index].onCompletion = function(){ createNations(index) }; // Specify function that will be executed after file has been found
ajax[index].runAJAX(); // Execute AJAX function
}
}
function createNations(index)
{
var obj = document.getElementById('victor');
eval(ajax[index].response); // Executing the response from Ajax as Javascript code
}
</script>
excerpt from the PHP database retrieval script (getPlayData.php):
$gameName = mysql_real_escape_string($_GET['gameName']);
$q = "SELECT a, b, c FROM table WHERE game='$gameName' ORDER BY num ASC";
$r = mysql_query($q);
echo "obj.options[obj.options.length] = new Option('#','');\n";
while ($row = mysql_fetch_row($r)) {
$string = mysql_real_escape_string(($row[0].' - '.$row[1])); // needed so quotes ' " don't break the javascript
echo "obj.options[obj.options.length] = new Option('$string','$row[2]');\n";
}
echoing the obj.options is the stock method this script was using. It seems ugly to me, but I don't know any javascript so I didn't want to fiddle with it.
The HTML is simple enough, just a table with a few empty <select> objects with IDs matching those in the javascript and onchange="getXXX(this)" calls.
My question is this: Everything works great for new records, but I'm at a loss as to how I can alter this to support marking one option from each select as selected, assuming I have that data in hand (ex: a user is editing an existing record) ?
Many thanks!
You can see this tutorial for creating an option that is selected as default. http://www.javascriptkit.com/javatutors/selectcontent.shtml One parameter in the option constructor dictate that whether the option is selected or not.
In the PHP file you will edit as follow:
$gameName = mysql_real_escape_string($_GET['gameName']);
$q = "SELECT a, b, c FROM table WHERE game='$gameName' ORDER BY num ASC";
$r = mysql_query($q);
echo "obj.options[obj.options.length] = new Option('#','');\n";
while ($row = mysql_fetch_row($r)) {
$string = mysql_real_escape_string(($row[0].' - '.$row[1])); // needed so quotes ' " don't break the javascript
if ($string ......)
echo "obj.options[obj.options.length] = new Option('$string','$row[2]', false, true);\n";
else
......
}

Categories