I am scraping sites, and I am doing this one at a time, and then trying to get the results to display AS I get them. I am trying to render one TR at a time, but instead, it does every single one, and then renders ALL the TRs.
Here is the call to javascript:
<body onload="getOffers(companies , {$scraped}, {$isbn13});">
Here is the JS/Jquery function:
function getOffers($company_ids, $scraped, $isbn)
{
if($scraped)
{
$.ajaxSetup({cache: false});
for(var $id in $company_ids)
{
$.ajax({
url: "../get_offer.php",
data: "id=" + $company_ids[$id] + "&isbn=" + $isbn + "&code=" + $id,
dataType: "html",
success: function(data) {
$("#results tbody:last").append(data);
}
});
}
}
else
{
return true;
}
}
And here is the PHP page:
<?php
require_once 'scrape.php';
require_once 'include.php';
$id = requestValue('id');
$isbn = requestValue('isbn');
$code = requestValue('code');
$page = curlMultiRequest(isbn10($isbn), $id);
$offer = getOffer($code, $page[$code], isbn10($isbn));
print "<tr><td>". $offer['company']."</td><td>". $offer['offer_new'] . "</td><td>" . $offer['offer_used']."</td></tr>";
?>
I tried returning the sting I am printing, but that didn't even work. How can I make it print each table row to the screen as the data is retrieved?
EDIT: so I tried adding this:
print "<tr><td>". $offer['company']."</td><td>". $offer['offer_new'] . "</td><td>" . $offer['offer_used']."</td></tr>";
ob_flush();
flush();
To the PHP and it didn't work. I don't understand, if I throw an alert, it happens on the fly for every ID, but the html rendering does not.
It may have magically fixed itself because your browser was caching some of the javascript. You should use some developer tools to manually flush the cache of resources for the host you are testing on to avoid old code being subtly used ....
Related
I need to loop through some data that was posted to a PHP page through AJAX. I've read about a dozen answers here and none are working for me. This is what my data object looks like before the post:
{"sessionValues":[{"ProductID":"507","State":"CHECKED"}, {"ProductID":"204","State":"UNCHECKED"}]}
I then post it like this:
$.ajax({
url: 'setSessionValues.php',
type: 'post',
data: {"session" : JSON.stringify(postObj)},
success: function(data) {
console.log(data); // Hello worldData: , Data: ,
}
});
This is the last thing that I tried in PHP:
if (isset($_POST["session"])) {
echo "Hello world";
$session = json_decode($_POST["session"]);
echo "Data: " . $session->sessionValues[0]->ProductID . ", " . $session->sessionValues[0]->State;
$session = json_decode($_POST["session"], true);
echo "Data: " . $session['sessionValues'][0]['ProductID'] . ", " . $session['sessionValues'][0]['State'];
}
Everything I've tried either throws out blanks or errors.
Edit:
Turns out that it doesn't like my data. Syntax Error: Unexpected end of input. Any ideas on that?
The second thing (xdebug is the first one) you should have tried in PHP is
if (isset($_POST["session"])) {
$session = json_decode($_POST["session"]);
print_r($session);
I want to refresh two variables named profittext and sumtext which will be refreshed and echoed in the following places every few seconds. I know AJAX is needed to do this but how do i actually make it work ? The only way i found out was to refresh the content of the whole file. is there any way to refresh specific variables? Any answers will be greatly appreciated . Thank you very very much.
<table>
if($profitandloss<$zero) {
$profitText = "<div style=\"color: red;\">$profitandloss</div>";
} elseif ($profitandloss>$zero) {
$profitText = "<div style=\"color: green;\">$profitandloss</div>";
}
// for profit and loss counting
$sum+= $profitandloss;
//
echo "<tr><td>" . $row['trade_id'] .
"</td><td>" . $row['selection'] .
"</td><td>" . $row['date'] .
"</td><td>" . $row['type'] .
"</td><td>" . $row['size'] .
"</td><td>" . $row['bidprice'] .
"</td><td>" . $row['offerprice'] .
"</td><td>" . $row['stoploss'] .
"</td><td>" . $row['takeprofit'] .
"</td><td>" . $profitText .
"</td><td><a href ='delete.php?id=".
$row['trade_id']."'>X</a>
</td></tr>";
$profitandloss=0;
if($sum<$zero) {
$sumText = "<div style=\"color: red;\">$sum</div>";
} elseif ($sum>$zero) {
$sumText = "<div style=\"color: green;\">$sum</div>";
}
}
echo "</table><br>";
?>
<!DOCTYPE html>
<html>
<table style="border:1px solid black;">
<tr>
<th style="border:1px solid black;">Profit/Loss</th>
</tr>
<tr>
<td style="border:1px solid black;"><?php echo $sumText ;?></td>
</tr>
</table>
</html>
I struggled with the concept of how to structure such code when I first started too. Although it's not specific to your particular variables, here's a quick example for how to update a var through AJAX with jQuery/PHP.
Prologue: If this is something you're going to be doing often, you'll want to learn jQuery, rather than using normal javascript alone. There are lots of great, free, resources on how to learn jQuery. Alternatively, if you're not satisfied with the free tutorials online, this is an excellent book. I'll write the example in jQuery.
Design: Okay, so the way it works is this:
Set a timer in javascript to execute a particular function every X seconds (you DO NOT want to do it every second).
That function makes an AJAX call (with jQuery) to a .PHP file on the server, sending it the data necessary so that the .PHP code knows what to send back.
The .PHP code grabs the data required (e.g., with MySQL) encodes it in a JSON format, and exits.
A promise on the AJAX call is fired and the data sent from PHP is received. Process it as you will.
Repeat from step 2.
If you have any questions about what the code is doing, please ask.
AJAX.PHP
<?php
$mysqli = new mysqli("localhost", "my_user", "my_password", "world");
$return_obj = array();
$request_obj = NULL;
// our AJAX call used "POST" as it's 'type', so we look in that
// variable.
if ( array_key_exists("func",$_POST) ) {
if ( $_POST['func'] === "get_update" ) {
if ( array_key_exists("which_var",$_POST) ) {
$which_var = $_POST['which_var'];
$which_var = $mysqli->real_escape_string($which_var); // should use prepared statements
// we sent 'num_people_logged_in' as our value here, so we'll be looking for a column/field
// with that value. this assumes that some other code, somewhere else,
// is regularly updating the table. it also assumes that there will only
// be a single row returned, which will hold the value.
$query = "SELECT '$which_var' FROM site_stats ";
if ( $result = $mysqli->query($query) ) {
if ( $row = $result->fetch_assoc() ) {
$request_obj[$which_var] = $row[$which_var];
}
}
}
}
}
$return_obj['request'] = $request_obj;
echo json_encode($return_obj);
die();
?>
MYCODE.JS
// this actually sends the AJAX request to the server.
function getUpdate() {
var jqXHR = $.ajax({
url : "ajax.php",
data : {
'func' : 'get_update',
'which_var' : 'num_people_logged_in'
},
dataType : 'json',
type : 'POST',
timeout : 10000
});
// attach 'promises' to the jqXHR object, which represents
// the AJAX call itself. 'promises' are, in this context,
// just events.
jqXHR.done(function(data,textStatus,jqXHR) {
// this executes if the AJAX call succeeded.
// the variable 'data' holds what the server
// sent us.
if ( ( data ) && ( data.request ) ) {
receiveUpdate(data.request);
}
});
jqXHR.fail(function(jqXHR,textStatus,errorThrown) {
// this executes if it failed
console.log("Fail: " + textStatus + " (" + errorThrown + ")");
});
jqXHR.always(function(a,textStatus,c){
// this executes either way, after .done or .fail
});
}
// this is called from jqXHR.done, on success
function receiveUpdate(request_obj) {
if ( request_obj.num_people_logged_in ) {
updateDOM(request_obj.num_people_logged_in);
}
}
function updateDOM(num_people_logged_in) {
if ( num_people_logged_in ) {
$("#mydiv > p.update").html("The updated value is: " + num_people_logged_in);
}
}
var timeoutID = null;
// setup our timer, to periodically make an
// AJAX call
function init() {
timeOutID = setInterval(function(){
getUpdate();
},5000);
}
// stop the timer
function cleanup() {
clearTimeout(timeoutID);
}
INDEX.HTML
<!DOCTYPE html>
<html>
<head>
<meta charset='utf-8'>
<title>AJAX practice</title>
<!-- <link href="mycss.css" rel='stylesheet'> if needed -->
<script src="http://code.jquery.com/jquery-1.9.1.js"></script>
<script src="mycode.js"></script>
<script>
$(document).ready(function() {
init();
$("#cleanup").on("click",function(){
cleanup();
});
}); // end ready
</script>
</head>
<body>
<div id='mydiv'>
<p>
How many people are online?
</p>
<p class='update'>
</p>
</div>
<button id='cleanup'>Stop updating!</button>
</div>
</body>
</html>
You will needd two PHP pages:
- one with HTML and JS, which periodicly makes ajax calls and puts the result to the HTML
- second with json (or even plain text) output of your dynamic data piece
Unfortunately, writing the full code in the answer is not someting that people do at stackoverflow, so just look at small example below, and try to figure out the missing parts.
http://jsfiddle.net/AMEqz/
var xhr = new XMLHttpRequest();
xhr.onload = function(r) {
// your render logic HERE
setTimeout(send, 1000);
}
function send() {
xhr.open("GET", "/", true);
xhr.send();
}
send();
p.s.: keep in mind that each ajax request will mean extra connection to your server, so make sure it can deal with the load ;)
Use a timer : https://developer.mozilla.org/en/docs/DOM/window.setInterval
setInterval(function(){
//update your var here
},1000);
I'm building an audio player that makes 3 different API calls, and I need them all to be in JSONP format, so I made a PHP proxy file that determines the output of the JSON data like so:
$datatype = $_GET["type"];
$artist = urlencode($_GET["artist"]);
$album = urlencode($_GET["album"]);
$content = "";
if($datatype == 'albumart'){
$content = file_get_contents('http://ws.audioscrobbler.com/2.0/?method=album.getinfo&api_key=037358e302c80571663e6a7a66b1dc05&artist=' . $artist . '&album=' . $album . '&format=json');
} elseif($datatype == 'artistart'){
$content = file_get_contents('http://ws.audioscrobbler.com/2.0/?method=artist.getinfo&api_key=037358e302c80571663e6a7a66b1dc05&artist=' . $artist . '&autocorrect=1&format=json');
} else {
$content = file_get_contents('http://cjzn.streamon.fm/metadata/recentevents/CJZN-48k.json');
}
header('Content-type: application/json; charset=utf-8');
echo $_GET['callback'] . '(' . json_encode($content) . ')';
Upon testing the output it seems to work fine, it gets the respective API data, wraps it in the JSONP () and accepts a JSONP callback.
Bur when I try and use it in my Javascript file it doesn't seem to work, but I can't figure out why! Here's an example of one of the functions being used to call the JSON data:
function getAlbumArt(artist,album){
var dataArtist = artist,
dataAlbum = album,
albumArtURL;
$.ajax({
url: 'jsonproxy.php',
dataType: 'jsonp',
data: {
type: 'albumart',
artist: dataArtist,
album: dataAlbum
},
success: function(data) {
if(data.album.image[4]["#text"]){
var albumArtURL = data.album.image[4]["#text"];
$('section.player div.album-artwork').css({'background-image':'url("' + albumArtURL + '")'});
} else {
getArtistArt(dataArtist);
}
},
error: function() {
getArtistArt(dataArtist);
alert('Sorry, unable to retrieve album artwork!');
}
});
}
Can anyone help with why this doesn't work for me?
Edit
I did alert(data); on success, and that returned all of the data from the feed, after that if I did something more specific like alert(data.album.image[4]["#text"]); it returned undefined. Very confused here. Anyone have any thoughts?
I think this is more down to timing than code, so really I am looking for best practice advice on how best to get a JSON response.
<script type="text/javascript">
$(window).load(function() {
$('#messages').append('<img src="images/loading.gif" alt="Currently Loading" id="loading" />');
var ideaid = <?php echo $_GET['ideaid']; ?>;
$.ajax({
url: 'sql/ajaxsql.php',
type: 'POST',
data: 'switch=commentList&ideaid=' + ideaid + '&filter=sortdate',
dataType: 'json',
success: function(result) {
var len = result.length;
var html;
console.log('length= ' + len);
$('#response').remove();
console.log(result);
for(var i = 0; i < len; i++) {
var pic = '<img src="https://graph.facebook.com/' + result[i].user_id + '/picture&type=small" align="middle" />';
var authname;
FB.api('/' + result[i].user_id + '?fields=name', function(AuthName) {
console.log(AuthName);
alert(AuthName.name);
authname = AuthName.name;
});
html = '<p>' + result[i].comment + '<br><hr>Date Added: ' + result[i].date + ' by ' + pic + ' ' + authname + '<br><hr><hr></p>';
$('#comms').append(html);
}
$('#loading').fadeOut(500, function() {
$(this).remove();
});
}
});
return false;
});
</script>
With this code, it fires off to get comments regarding a certain idea (idea_id). The comments only holds the Users ID (facebook). When all the data is back, the success then sorts the data ready to print to the screen in some order.
As part of the success, I have the date, time, FB image and name as part of the Author Info under each comment.
Date and Time, works. Image using the graph works, but the name is a bit late of the window loading, and so misses it's call, so comes back as undefined and then the Alert pops up with the name. I understand ajax is meant to do this.
Whats the best way to get round this.
Thank you in advance.
Andrew
EDIT
I have been unable to make this work, even with the suggestions below.
EDIT AGAIN Just seen bf new updated version as below. would also have worked. But I have spent a day on this one function and dare not to play.
As soon as the FB.api comes into play, I could not get the values from out side it. So I took a different approach.
Rather than ajax, I used the query from the PHP side that gets the data, including the uid and then json queried that, and bolted it onto the (mysql_fetch_array) array as follows:
$gc_result = mysql_query($gc_query);
while ($result = mysql_fetch_array($gc_result)) {
$jsonURL = "https://graph.facebook.com/" . $result['user_id'] . "/";
$json = json_decode(file_get_contents($jsonURL), true);
$result["name"] = $json['name'];
$data[] = $result;
}
echo json_encode($data);
Now I have that, I can then do the following and call it within the jQuery:
for(var i = 0; i < len; i++) {
var pic = '<img src="https://graph.facebook.com/' + result[i].user_id + '/picture?type=small" align="middle" />';
html = '<p>' + result[i].comment + '<br><hr>Date Added: ' + result[i].date + ' by ' + pic + ' ' + **result[i]['name']** + '<br><hr><hr></p>';
$('#comms').append(html);
}
This all works great, and I am a complete novice to programming jquery and using Facebook API and JSON, but even I sit back and am pretty impressed with this solution. Before I get carried away, are there any potential flaws in this, performance or security wise ???
Thanks again in Advance.
Andrew
The call to FB.api is probably asynchronous (another ajax request), so you have to move the code after it to inside the FB.api callback:
FB.api('/' + result[i].user_id + '?fields=name', function(AuthName) {
console.log(AuthName);
alert(AuthName.name);
authname = AuthName.name;
html = '<p>' + result[i].comment + '<br><hr>Date Added: ' + result[i].date + ' by ' + pic + ' ' + authname + '<br><hr><hr></p>';
$('#comms').append(html);
});
You also have a variable scope problem because of the for loop. One of the ways to fix this is to use a separate function to create the callback. Add this right after your $(window).load block, before </script>:
function createFbApiCallback(jsonResult) {
return function(AuthName) {
var authname = AuthName.name;
var pic = '<img src="https://graph.facebook.com/' + jsonResult.user_id + '/picture&type=small" align="middle" />';
var html = '<p>' + jsonResult.comment + '<br><hr>Date Added: ' + jsonResult.date + ' by ' + pic + ' ' + authname + '<br><hr><hr></p>';
$('#comms').append(html);
}
}
Then change your loop to this:
for(var i = 0; i < len; i++) {
FB.api('/' + result[i].user_id + '?fields=name', createFbApiCallback(result[i]));
}
If you have to execute code that relies on a callback function inside another callback function, execute your code inside the most inner callback function. In your case, move all that is out of the FB API callback to be inside it, so all your DOM manipulation is done only when both the AJAX response and the FB.api response has returned.
I have two XML sources to retrieve data from. I want to use them alternately per page load. So when someone visits the page the first source will be used, next time the visit the page the other source will be used. Here is the ajax request I am using to get one data source:
$(document).ready(function() {
$.ajax({
type: "GET",
url: "source1.xml", //how do I alternately load two different xml data sources?
dataType: "xml",
success: function(xml) {
var counter = 0
var output = '<li>';
$(xml).find('person').each(function(){
counter++;
var image = $(this).find('image').text();
var name = $(this).find('name').text();
var title = $(this).find('title').text();
var company = $(this).find('company').text();
output = output + '<div><img src=img/' + image + '.jpg />' + '<br /><label><span>' + name + '</span><br />' + title + '<br />' + company + '</label><br /></div>';
if(counter % 3 === 0){
output = output + '</li><li>';
}
});
output = output + '</li>';
$('#update-target ul').html(output);
}
});
});
For extra info, here is how I am alternately loading 2 flash files using PHP:
if(isset($_SESSION['rotation'])){
$picker = $_SESSION['rotation'];
}else{
$picker = rand(0,1);
}
if($picker == 0){
echo '<script type="text/javascript">
var video1 = new SWFObject("somefile1.swf", "p1", "151", "590", "9", "#ffffff");
video1.addParam("wmode","transparent");
video1.write("meh");
</script>';
$_SESSION['rotation'] = ++$picker;
} else {
echo '<script type="text/javascript">
var video1 = new SWFObject("somefile2.swf", "p1", "151", "590", "9", "#ffffff");
video1.addParam("wmode","transparent");
video1.write("meh");
</script>';
$_SESSION['rotation'] = --$picker;
}
I realize I could just stick the jquery document ready code right in there where I have the js calling the flash but it does not seem like a very efficient way of handling this. What is a "best case" way to do this?
You can just use a variable to keep it short, like this:
echo '<script type="text/javascript">var xmlSource = "source1.xml";</script>';
Use that in an if caluse as well, then just reference that in your code:
url: xmlSource,
There are other ways of course, using a cookie (the cookie plugin), putting the text right in the document.ready handler, etc...whichever seems most elegant to you I suppose.
I recommend the variable from the PHP side or a cookie...both of these options allow the document.ready code to stay outside the page in an external script, and not downloaded by the user each time.