Link to home
Start Free TrialLog in
Avatar of helpchrisplz
helpchrisplz

asked on

swapping out text from php loop with js

hi all am new to javascript and need some help.

what am trying to make is a testimonial text slider / updater so i can show some nice customer feedback on a homepage for people to see how good we are rated.

the website has some guestbook submissions so i am getting them out of the database. I guess i want to loop through them and update the paragraph tag every 8 seconds then repeat this so it loops over all post and then restarts the loop over and over.

this is the code that i have managed to piece together by searching the internet.

<?php
// ADD PHP VARABLE TO ARRAY
$text= array();
	
	foreach($guestbook as $post) {
		$text[] = $post;
	}
?>

<script type="text/javascript">
var fromPHP=<? echo json_encode($text); ?>;

(function myLoop (i) {          
	setTimeout(function () {      
		for (i=0; i<fromPHP.length; i++) {

			var a= fromPHP[i];
			// update html with new text    
			 $("p").html(a);
			}

			if (--i) myLoop(i);      //  decrement i and call myLoop again if i > 0
   }, 8000)})(999999);               //  pass the number of iterations as an argument
</script>

Open in new window


i haven't tested my code yet but i want to know if this looks ok? and how i could animate the change in text (fade in) and is it ok to have a never ending loop, what should i load it in? document ready?
Avatar of Rob
Rob
Flag of Australia image

I would personally simplify it by requesting the new guestbook submission every 8 sec using AJAX.
To make it easier, use jQuery:

<?php
if (array_key_exists('post',$_POST)) {
$text= array('wow you guys rock','what a champion','will use you guys next time, everytime','i\'ll be back');

	/*
	foreach($guestbook as $post) {
	$text[] = $post;
}
*/
echo $text[rand(0,3)];
return;
// if a request is made then process and return
}
else {
	//echo "hi";
}
?>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">

<title>PhpFiddle Initial Code</title>

<script type="text/javascript" src="/js/jquery/1.7.2/jquery.min.js"></script>

<script type="text/javascript">
/* 
* PhpFiddles REST API with JSON HTTP response supports Cross-Origin Resource Sharing, 
* and can be used with normal Ajax call in any web pages, for example, jQuery Ajax
*/
$(document).ready(function() {
	setInterval(getNextPost, 2000);
});
	function getNextPost() {
		//alert('calling');
		$.ajax({
			url: "<?php echo $_SERVER["SCRIPT_NAME"]; ?>",	
			type: "POST",	   // or "GET"
			data: 'post=1',
			cache: false,
			success: function(data) {
					$('#update').text(data);
			},
			error: function(data) {
				alert(data.result);
			}
		});
	}

</script>

<style type="text/css">
	
</style>

</head>

<body>

<div id='update' style="margin: 50px 10%;">
... updating ...
</div>

</body>
</html>

Open in new window

ASKER CERTIFIED SOLUTION
Avatar of Rob
Rob
Flag of Australia image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
If I read your code correctly you are going to be looping around and on each iteration calling myloop with a value of i - which is just overwritten. Each loop starts a new timer before the loop is finished - so it is going to grow exponentially - likely to crash everything.

Is this not what you want to do
var i = 0;
function myLoop()
{
    // Get the next item from the array of posts. We do this by
    // incrementing the i var and then taking the mod of this with the 
    // length which will produce an index in the range 0 to length-1

    var index = ( (i++) % fromPHP.length );

    // Fade out existing content, set new content and fade it back in again
    $("p").fadeOut('slow', function() {
         $("p").html(fromPHP[index]).fadeIn();
    });
}
$(function() {
    setInterval("myLoop()", 8000);
});

Open in new window

I have not tested this but the principle should be sound.
Avatar of helpchrisplz
helpchrisplz

ASKER

Hi thanks for your help so far.

i have taken tagits example. What i have managed is:

got my data out the DB and into my array (s). I have tested my arrays so i know by code is working up to this point. now i am trying to update the html with 2 data changes. Can you just take a look at my code below to tell me what am doing wrong then i will be sorted. thank you.


// print_r ($text); my arrays are collecting the data! test successful!
// print_r ($name);

if (array_key_exists('post',$_POST)) {
	echo $text[rand(0,3)];
	echo $name[rand(0,3)];
	return;
	// if a request is made then process and return
}
else {
	//echo "hi";
}  
?>

<script type="text/javascript">
/* 
* PhpFiddles REST API with JSON HTTP response supports Cross-Origin Resource Sharing, 
* and can be used with normal Ajax call in any web pages, for example, jQuery Ajax
*/
$(document).ready(function() {
	setInterval(getNextPost, 2000);
});
	function getNextPost() {
		//alert('calling');
		$.ajax({
			url: "<?php echo $_SERVER["SCRIPT_NAME"]; ?>",	
			type: "POST",	   // or "GET"
			data: 'post=1',
			cache: false,
			success: function(data) {
					$('.quote').text(data);
					$('.test').name(data);
			},
			error: function(data) {
				alert(data.result);
			}
		});
	}

</script>



<div class="quote-box">
            <p class="quote">... updating ...</p>
          </div>
          <img class="quote-thingy" src="<?php echo $this->getThemePath()?>/images/9664dfda-13ef-49c9-b1e4-7bd6171e8aee_11-nubbin.png" width="42px" alt="9664dfda-13ef-49c9-b1e4-7bd6171e8aee_11-nubbin.png">
          <div class="w-clearfix by-section">
            <img class="person-icon" src="<?php echo $this->getThemePath()?>/images/82116c16-8d7d-444d-8ee6-de9ecd0fbba5_13-person-dude.png" width="66px" alt="82116c16-8d7d-444d-8ee6-de9ecd0fbba5_13-person-dude.png">
            <h3 class="test">... updating ...</h3>
          </div>

Open in new window

Ok even though it should and probably does work, I wouldn't reference your quote and test <p> fields by class.  Give them an ID and reference them using the # instead of the .

that said your code looks ok.  Is it not doing something you're expecting it to?

Not sure if you're aware that:
echo $text[rand(0,3)];
echo $name[rand(0,3)];

Open in new window

will only return a random value from the first 4 elements of each array.  
Also worth nothing is whether the $name and $text arrays are related. ie does $text[3] relate to $name[3] as the above code will only "randomly" line up with the same index.  If they do relate then you'd need this
$rand_index = rand(0,3);
echo $text[$rand_index];
echo $name[$rand_index];

Open in new window

in other words

<p class="quote">... updating ...</p>

becomes

<p id="quote">... updating ...</p>

and

<h3 class="test">... updating ...</h3>

becomes

<h3 id="test">... updating ...</h3>

then your code:

$('#quote').text(data);
$('#test').text(data);

Open in new window

if (array_key_exists('post',$_POST)) {
	echo $text[rand(0,3)];
	echo $name[rand(0,3)];
	return;
	// if a request is made then process and return
}

Open in new window


The above is going to dump one long string - when it arrives at the success function both the .quote and .text elements will end up with the same string. If you are goin to go the AJAX route (not sure if that is the right way - if you have small number of text items then your original solution is better) but if you are then
$result = array();
$index = rand(0,3); // In case text and name are related
if (array_key_exists('post',$_POST)) {
	$result['text'] = $text[$index];
	$result['name'] = $name[$index];
}
die(json_encode($result));

Open in new window

In your success function
		$.ajax({
			url: "<?php echo $_SERVER["SCRIPT_NAME"]; ?>",	
			type: "POST",	   // or "GET"
			data: 'post=1',
			cache: false,
			dataType: 'json', // Add this
			success: function(data) {
                                        // JSON object returned
					$('.quote').text(data.text);
					$('.test').name(data.name);
			},
			error: function(data) {
				alert(data.result);
			}
		});

Open in new window

(no points for this comment, I think it's good to reiterate this point)

@JulianH's made a good point about your method of sending data back to the browser.

It makes more sense as he's pointed out to collect the data, encode it and then send it back (with the die()).  

Side note for @JulianH: Curious as to your use of die() and not something like:

echo json_encode($result); 
return;

Open in new window

@tagit,
old habbit - make sure the script terminates at that point - effect is the same - but no ambiguity about what happens next ...
thanks and sure makes no difference just seems more violent ;)
hi thanks for everything you have both helped me understand better.

where am at:
am getting undefined :(

when using die(json_encode($result)); my page source stopped with [] so i used

echo json_encode($result);
      return;      

not sure how to fix the undefined pop up.

code so far:

$result = array();
$index = rand(0,3); // In case text and name are related
if (array_key_exists('post',$_POST)) {
	$result['text'] = $text[$index];
	$result['name'] = $name[$index];
	// print_r ($result); this outputs one text and name successfully.
	echo json_encode($result); 
	return;	
}
?>
<script type="text/javascript">
$(document).ready(function() {
	setInterval(getNextPost, 2000);
});
	function getNextPost() {
		//alert('calling');
		$.ajax({
			url: "<?php echo $_SERVER["SCRIPT_NAME"]; ?>",	
			type: "POST",	   // or "GET"
			data: 'post=1',
			cache: false,
			dataType: 'json', 
			success: function(data) {
                   // JSON object returned
					$('#quote').text(data.text);
					$('#test').name(data.name);
					
			},
			error: function(data) {
				alert(data.result);
				// am getting undefined :(
			}
		});
	}
</script> 

<div class="quote-box">
            <p id="quote" class="quote">... updating ...</p>
          </div>
          <img class="quote-thingy" src="<?php echo $this->getThemePath()?>/images/9664dfda-13ef-49c9-b1e4-7bd6171e8aee_11-nubbin.png" width="42px" alt="9664dfda-13ef-49c9-b1e4-7bd6171e8aee_11-nubbin.png">
          <div class="w-clearfix by-section">
            <img class="person-icon" src="<?php echo $this->getThemePath()?>/images/82116c16-8d7d-444d-8ee6-de9ecd0fbba5_13-person-dude.png" width="66px" alt="82116c16-8d7d-444d-8ee6-de9ecd0fbba5_13-person-dude.png">
            <h3 id="test" class="test">... updating ...</h3>
          </div>

Open in new window

SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
i have added your suggestions and still get the undefined so using:
http://localhost/sites/tseoc/?post=1
with $_REQUEST

i see this in the source code:
{"text":"Can.t thank you enough for the fantastic job you have done in promoting The Suitcase Saver.  Three enquiries this week from uk airports, Spain and Belgium and I know they have came from your hard work...","name":"Karen Duncan"}

could it be because the ajax isn't allowed to access my page?
All my code is on my homepage that is part of a theme i built for the CMS concrete5.
at the top of the themes template i have <?php  defined('C5_EXECUTE') or die(_("Access Denied.")); ?>

if i remove that it still says undefined though.
if i put it back to POST then i dont see anything in Console after refresh
ok testing away from the CMS.

i have created a index.php in the root of my xampp htdocs with the following code:

still getting undefined though.

<script src="//ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>  

<?php
$text= array('wow you guys rock','what a champion','will use you guys next time, everytime','i\'ll be back');
$name= array('bob','beeb','hotbill','i\bebbbf');
$result = array(
    'text' => '', 
    'name' => ''
);
$index = rand(0,3); // In case text and name are related
if (isset($_POST['post'])) {
	$result['text'] = $text[$index];
	$result['name'] = $name[$index];
	// print_r ($result); this outputs one text and name successfully.
	echo json_encode($result); 
	return;	
}
?>
<script type="text/javascript">
$(document).ready(function() {
	setInterval(getNextPost, 2000);
});
	function getNextPost() {
		//alert('calling');
		$.ajax({
			url: "<?php echo $_SERVER["SCRIPT_NAME"]; ?>",	
			type: "POST",	   // or "GET"
			data: 'post=1',
			cache: false,
			dataType: 'json', 
			success: function(data) {
                   // JSON object returned
					$('#quote').text(data.text);
					$('#test').name(data.name);
					
			},
			error: function(data) {
				alert(data.result);
				// am getting undefined :(
			}
		});
	}
</script> 

<p id="quote" class="quote">... updating ...</p>        
<h3 id="test" class="test">... updating ...</h3>

Open in new window

its working when i do it like this: with doctype

<?php
$text= array('wow you guys rock','what a champion','will use you guys next time, everytime','i\'ll be back');
$name= array('bob','beeb','hotbill','i\bebbbf');
$result = array(
    'text' => '', 
    'name' => ''
);
$index = rand(0,3); // In case text and name are related
if (isset($_POST['post'])) {
	$result['text'] = $text[$index];
	$result['name'] = $name[$index];
	// print_r ($result); this outputs one text and name successfully.
	echo json_encode($result); 
	return;	
}
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">

<script src="//ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>  
<script type="text/javascript">
$(document).ready(function() {
	setInterval(getNextPost, 2000);
});
	function getNextPost() {
		//alert('calling');
		$.ajax({
			url: "<?php echo $_SERVER["SCRIPT_NAME"]; ?>",	
			type: "POST",	   // or "GET"
			data: 'post=1',
			cache: false,
			dataType: 'json', 
			success: function(data) {
                   // JSON object returned
					$('#quote').text(data.text);
					$('#test').text(data.name);
					
			},
			error: function(data) {
				alert(data.result);
				// am getting undefined :(
			}
		});
	}
</script> 
</head>
<p id="quote">... updating ...</p>        
<h3 id="test">... updating ...</h3>

</body>
</html>

Open in new window

ok so my php has to go above my doctype for it to work...

lol grrr
Its not working when i put the code above my doctype; in my CMS theme but it does work when i test outside of the CMS. I will try and read up on using ajax in concrete5

i found this link that i expect will help me: http://www.concrete5.org/community/forums/block_requests/ajax-call-access-denied./


thanks!
You should not put the php in the same file as your output code. It should go in its own php file. It has only one purpose and that is to send back the text - don't mix that up with your index file.

Also time to move to HTML5 maybe ... doctype is a bit outdated.
ye i use Html5 in my themes.. was only useing that doctype as tagits example code used it.

why did i need to use url: "<?php echo $_SERVER["SCRIPT_NAME"]; ?>",:
when i shouldn't have it all in one file?

it echos the root url.

 

thanks.
That was based on the assumption that you would be calling back to the page that contained the AJAX call.

You can do it that way but personally I prefer my AJAX functions to be in spearate scripts. They perform very specific tasks with very specific output that usually does not require a full doctype / head /body declaration - so mixing them up with a script that has those things is potentially a problem.

I would simply hard code the path to the script that handles the request in place of echo'ing the SCRIPT_NAME server var out.
That was there for testing. Posting back to the same file makes it easier to show what's going on but Julian is right, it is good practice to have the components separated
ok thanks am looking at this now for more understanding of the CMS
http://www.concrete5.org/marketplace/addons/ajax-lessons/