Link to home
Start Free TrialLog in
Avatar of Steve Tinsley
Steve TinsleyFlag for United Kingdom of Great Britain and Northern Ireland

asked on

Ajax to create array

I have a php page that creates a world cloud:

<?php
$id = $_GET['id'];

try
{
	$sql = "SELECT * FROM wordcloud WHERE questionID = $id";
	$sql = $datadb->prepare($sql);
  	$sql->execute(array());
}

catch(PDOException $e)
{
	echo $e->getMessage();
	die;
}

?>

<script type="text/javascript">

var word_list = [
	<?php
	   while($r = $sql->fetch(PDO::FETCH_ASSOC)){
			echo "{text: \"" . $r['keyword'] . "\", weight:". $r['weight'] ."},";
		}
	?>
];

$(document).ready(function() {
    $("#dynamic_wordcloud").jQCloud(word_list);
});

</script>

<div id="dynamic_wordcloud"></div>

Open in new window


But I want to get the data using an ajax call.
I have written the serverside php bit which outputs
[{"text":"word1","weight":"2"},{"text":"word2","weight":"1"}]

Open in new window


But im not sure how to get it into the javascript. This is my JS so far:

<script type="text/javascript">

function getWordcloudData(questionID) {
	$.get('../library/process_output.php?action=outputWordcloudData&questionID=' + questionID, function(data) {
		var resultSet = jQuery.parseJSON(data);
		return resultSet;
	});
}

var word_list = getWordcloudData( <?php echo $_GET['id']; ?> );

$(document).ready(function() {
    $("#dynamic_wordcloud").jQCloud(word_list);
});

</script>
<div id="dynamic_wordcloud"></div>

Open in new window


I am getting the error: Uncaught TypeError: Cannot read property 'length' of undefined

Im sure its something really obvious, but i'm not sure what it is.
Avatar of Rob
Rob
Flag of Australia image

First I would try changing the get to getJSON

$.getJSON('../library/process_output.php?action=outputWordcloudData&questionID=' + questionID, function(data) {
       console.dir(data); // see what is output to the console
            //var resultSet = jQuery.parseJSON(data);
            //return resultSet;
      });

Also move the following inside your $(document).ready()

ie
$(document).ready(function() {
var word_list = getWordcloudData( <?php echo $_GET['id']; ?> );
$("#dynamic_wordcloud").jQCloud(word_list);
});
Avatar of Steve Tinsley

ASKER

OK. Im getting this back into the contole
User generated image
There might be something useful in this article:
https://www.experts-exchange.com/articles/22519/Understanding-JSON-in-PHP-and-JavaScript-Applications.html

A JSON string is JavaScript.  You should be able to use console.log and alert() to visualize the information in the JSON string.  From the current message, I'm confused by the reference to the property 'length' which does not seem apparent in your code.  If you haven't tried yet, you might want to run this in Chrome with Dev Tools turned on.  You may be able to find where 'length' is coming from.  Good learning resources for Chrome Dev Tools here:
https://www.codeschool.com/courses/discover-devtools

You might also want to deconstruct the problem a bit - examine each piece of data looking at inputs and outputs from the subcomponents.  Ask questions like "Does the PHP script always work predictably?" and "Can I see the returned JSON string in a browser request to the PHP script?"

Also, are you confident in jQCloud's usability?  Are there others who are using it successfully?  If this is the one you're using, the gallery links are not very inspiring.
https://github.com/lucaong/jQCloud
Ahh, that image helps.  The error appears to be in jQCloud itself.  Maybe look for another plug-in?
ok if you did exactly what I had above, the function wasn't returning the data so go ahead and do that now:
ie.
$.getJSON('../library/process_output.php?action=outputWordcloudData&questionID=' + questionID, function(data) {
    return data;
});

You've proved it is in the right format, an array of js objects so if there's still that "length" issue then it could be as Ray says and a problem with the plugin.  See how that goes above and we'll be able to do some more testing if there's still an issue.
In fact, here is a demo of it working so I suspect it could be your data:

http://jsbin.com/gipujo/edit?html,output
So when I do it like your jsbin example it works

      $(function() {
        // When DOM is ready, select the container element and call the jQCloud method, passing the array of words as the first argument.
        $.getJSON('../library/process_output.php?action=outputWordcloudData&questionID=' + <?php echo $_GET['id']; ?>, function(data) {
          $("#dynamic_wordcloud").jQCloud(data);  
        });

Open in new window



but when I do it with the ajax call in a separate function it doesn't:

function getWordcloudData(questionID) {
	$.getJSON('../library/process_output.php?action=outputWordcloudData&questionID=' + questionID, function(data) {
		return data;
	});
}

$(function() {
	var word_list2 = getWordcloudData( <?php echo $_GET['id']; ?> );
    $("#dynamic_wordcloud").jQCloud(word_list2);
});

Open in new window


is it something to do with the jQCloud function running before the ajax call has returned data??

Its working your way now but would be good to understand how to sort it my way.
Perhaps I could show a loading spinner whilst the ajax function is running?
Just a scope issue as this returns data from the callback function, NOT your function.

$.getJSON('../library/process_output.php?action=outputWordcloudData&questionID=' + questionID, function(data) {
           return data;
     });

What you're after to do it your way is:

function getWordcloudData(questionID) {
    var someTempVariable = []; // an empty array
      $.getJSON('../library/process_output.php?action=outputWordcloudData&questionID=' + questionID, function(data) {
            someTempVariable = data;
      });
    return someTempVariable;
}

However you could just set up the jQCloud in the ajax callback and show a spinner / "loading..." while that's happening (as you suggested)
Im so sorry to keep asking...
I think its SO close

<script type="text/javascript">

function getWordcloudData(questionID) {
    var someTempVariable = [];
      $.getJSON('../library/process_output.php?action=outputWordcloudData&questionID=' + questionID, function(data) {
            someTempVariable = data;
      });
      alert (someTempVariable); //<--- this is empty
    return someTempVariable;
}


// $(function() {
// 	$.getJSON('../library/process_output.php?action=outputWordcloudData&questionID=' + <?php echo $_GET['id']; ?>, function(data) {
// 		$("#dynamic_wordcloud").jQCloud(data);  
// 	});
// });

$(function() {
	var word_list = getWordcloudData( <?php echo $_GET['id']; ?> );
    $("#dynamic_wordcloud").jQCloud(word_list);
});

</script>

Open in new window


someTempVariable is returning nothing :(
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
I'm wondering a little bit about the sequence of events.  Is PHP putting the correct value into this statement?  If you turn on error_reporting(E_ALL) you may be able to detect something like a missing value for $_GET['id']
var word_list = getWordcloudData( <?php echo $_GET['id']; ?> );

Open in new window

Here is why I'm wondering about that statement.  

PHP runs on the server and creates the "document" from HTML, CSS and JavaScript.  So when we see JavaScript with a direct PHP call in it, something seems out of sequence.  PHP should have already run on the server and should have already put the "id" value into the JavaScript function call.  This would happen before the JavaScript was sent to the client browser for action and display.  If you need a dynamic call from the client back to the server, you would need to use AJAX to send the values to the PHP script on the server.
If you were to do it by calling a function like you had, you're "blocking" execution waiting for the results to be returned from the request.

This is where view models and their associated framewords come into play such as knockoutjs and angularjs as they keep track of variables and when they change, that change is captured and you can do something like initialise a WordCloud.  Overkill in this instance but worth considering for anything more complex