Hello all,

I have a problem with some AJAX code that I'm working on. There are three different parts to my problem. The goal of this code is to have a a link that says, "Show comments" to display the comments for a post from an admin underneath the update. Hopefully the code below will help clarify.

This is the code for the loop on the index page that actually displays the update and the line that says Show Comment. This file has imported the viewComment.js file so that is not the problem.

echo '<div id="pagename"><h3>Updates</h3></div><br />';
	echo '<ul>';
	
	while($update_array = mysqli_fetch_array($update_data)){
		$poster_query = "SELECT username FROM wwit_user WHERE user_id=".$update_array['amsg_poster_id']."";
		$poster_data = mysqli_query($dbc, $poster_query);
		$username = mysqli_fetch_array($poster_data);
		echo '<li><div id="update">'. $update_array['amsg_text'] . '</div> <div id="time">'. $update_array['amsg_post_time'] . ' - Posted by <a href="viewprofile.php?user_id='.$update_array['amsg_poster_id'].'">'. $username['username'] .'</a></div></li>';
		?> <a href="#" onClick = "alert('<?php echo $update_array['amsg_id']; ?>'); startRequest('<?php echo $update_array['amsg_id']; ?>');">Show Comments</a> <?php
		echo 'comments_'. $update_array['amsg_id'];
		echo '<div id="comments_'. $update_array['amsg_id'] .'" class = "comments"></div>';
		echo '<br />';
	}
	echo '</ul></div><br /><br />';

Next is the code in the viewComment.js that actually handles the xmlHttpRequest. When the Show Comment line from above is clicked, it calls the startRequest() function. Pardon all of the alert() functions. I've been using them to see what part is failing, and so far everything works up until a line in the displayComment() function that I've commented on below.

var xmlHttp;
	var requestType = "";
	var id;
	var div_id;
	var url;
	
	function createXMLHttpRequest(){
		alert("something's working");
		if (window.ActiveXObject){
			xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
			alert("work");
		}
		else if (window.XMLHttpRequest){
			xmlHttp = new XMLHttpRequest();
			alert("You're using firefox/chrome/some other cool open-source browser");
		}
		else{
			alert("failure");
		}
	}
	
	function startRequest(parentId){
		alert("work");
		id = parentId;
		alert(id);
		createXMLHttpRequest();
		alert("keep checking");
		xmlHttp.onreadystatechange = handleStateChange;
		url = "/view_comment.php?parent_id=" + id;
		xmlHttp.open("GET", url, true);
		xmlHttp.send(null);
	}
	
	function handleStateChange(){
		if(xmlHttp.readyState == 4){
			if(xmlHttp.status == 200){
				alert("COOL BEANS " + id);
				displayComments(id);
				alert("I LOVE JAVASCRIPT");
			}
		}
	}
	
	function displayComments(){
		div_id = "comments_" + id;
		alert(div_id);
		var comments = document.getElementById(div_id);
		alert("get div_id works");
                //Here is where I run into the problem. The alert function above 
                //displays but not the one below that says "get comment works"
                //I think there is a problem with something in the line below
                //with the results variable
		var results = xmlHttp.responseXML.getElementsByTagName("comment");
		alert("get comment works");
		var user = null;
		var div = null;
		var url2 = null;
		alert("somethings working");
		
		for(var i=0; i< results.length; i++){
			div = document.createElement("div");
			div.setAttribute('id', "comment");
			user = document.createElement("a");
			url2 = "/viewprofile.php?user_id=" + results[i].childNode[2].nodeValue;
			user.setAttribute('href', url2);
			user.nodeValue = results[i].childNode[2].nodeValue;
			
			text = document.createElement("p");
			text.setAttribute('class', 'comment_text');
			text.nodeValue = results[i].childNode[3].nodeValue;
			
			time = document.createElement("p");
			time.setAttribute("id", "comment_time");
			time.nodeValue = results[i].childNode[4].nodeValue;
			
			div.appendChild(user);
			div.appendChild(text);
			div.appendChild(time);
			comments.appendChild(div);
		}
	}

Finally I have a php script to return the data values in xml format. I have not used xml a lot in the past so I think this is where I might have screwed up.

<?php
	$parent_id = $_GET['parent_id'];
	
	$dbc = mysqli_connect(DB_HOST, DB_USER, DB_PASSWORD, DB_NAME);
	$comment_query = "SELECT * FROM comments WHERE parent_id = '$parent_id' ORDER BY post_time ASC";
	$comment_data = mysqli_query($dbc, $comment_query);
	$comment_rows = mysqli_fetch_array($comment_data);
	
	xmlOutput = '<comments>';
	while($comment_rows){
		xmlOutput .= '<comment>';
		xmlOutput .= '<comment_id>'. $comment_rows['comment_id'] .'</comment_id>';
		xmlOutput .= '<poster_id>'. $comment_rows['poster_id'] . '</poster_id>';
		
		//Get username
		$username_query = "SELECT username FROM wwit_user WHERE user_id = '$comment_rows['poster_id']'";
		$username_data = mysqli_query($dbc, $username_query);
		$username_rows = mysqli_fetch_array($username_data);
		
		xmlOutput .= '<poster_name>'. $username_rows['username'] .'</poster_name>';
		xmlOutput .= '<comment_text>'. $comment_rows['comment_text'] .'</comment_text>';
		xmlOutput .= '<comment_time>'. $comment_rows['post_time'] .'</comment_time>';
		xmlOutput .= '</comment>';
	}
	xmlOutput .= '</comments>';
	echo xmlOutput;
?>

Sorry for throwing so much out at once, but I can't seem to find the problem. Hopefully a fresh pair of eyes will be able to find the problem. Thank you very much.

pHouse,

You may just need to add <?xml version="1.0"?> to the start of the xmlOutput string to make it recognisable as xml.

If you want, you can try doing the server-side code in jQuery instead of raw javascript. It will simplify considerably to something like:

function startRequest(parentId){
	var $comments = $("#comments_" + parentId);
	$.ajax(){
		url: "/view_comment.php?parent_id=" + parentId,
		type: "GET",
		dataType: "xml",
		success: function(xml, textStatus, jqXHR){
			var $div, text, time, user;
			var baseURL = "/viewprofile.php?user_id=";
			$(xml).find('comment').each(function(){
				var $children = $(this).children();
				user = $children.eq(2).text();
				text = $children.eq(3).text();
				time = $children.eq(4).text();
				$div = $("<div>").appendTo($comments);
				$("<a>").attr('href', baseURL+user).html(user).appendTo($div);
				$("<p>").addClass('comment_text').html(text).appendTo($div);
				$("<p>").html(time).appendTo($div);
			}
		}
	};
}

(untested)

Airshow

Thanks for the response Airshow, I tried adding the xml header to the beginning of the string that view_comment.php outputs but nothing happened differently. And as I have not really used JQuery much, I would prefer to keep using what I'm using right now.

pHouse,

You may get a clue as to what is wrong by inspecting the raw XML response.

You can do this by replacing alert("get comment works"); with alert(xmlHttp.responseText); .

Airshow

Thank you for the reply. I tried replacing the previous alert() with the alert function that you posted, yet nothing is displaying or visibly happening after the alert before it.

Any other suggestions? I've combed over all of the code looking for a problem but I cannot find anything. In the php script that I have, I even replaced it with static xml to see if that was the problem, but even that is not working. Any suggestions would be appreciated as I've been stuck on this problem for a long time.

From what you say, the problem must be with the line:

var results = xmlHttp.responseXML.getElementsByTagName("comment");

It's difficult for me to advise as I'm not expert in getting data from a returned XML document this way. I would use jQuery, as per the example I posted earlier.

Have you checked your browser's error console to see if that line throws an error?

Airshow

pH,

I've managed to get something working.

XML

<?xml version="1.0" ?>
<comments>
<comment><comment_id>0_01234</comment_id><poster_id>0_5678</poster_id><poster_name>Sam Smith</poster_name><comment_text>Comment AAAA</comment_text><comment_time>12:00</comment_time></comment>
<comment><comment_id>1_01234</comment_id><poster_id>1_5678</poster_id><poster_name>John Jones</poster_name><comment_text>Comment BBBB</comment_text><comment_time>15:00</comment_time></comment>
</comments>

NOTE: I found that the tags within each <comment></comment> needed top be closed up. Carriage returns threw things into disarray. This is probably just a feature of serving locally (file browsing) not via a proper HTTP server.

HTML/JavaScript

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head>
<title>Airshow :: Untitled</title>
<style type="text/css">
body {
	font-family: verdana;
}
h2 {
   margin:6px 0;
   font-size
}
.comments {
	width: 320px;
	padding: 3px 3px 0 3px;
	border: 1px solid #999;
}
.comment {
	margin: 0 0 3px 0;
	padding: 6px;
	font-size: 10pt;
	border: 1px solid #999;
	background-color: #c6e3f4;
}
.comment p {
	margin: 0;
}
.comment a {
	text-decoration: underline;
	font-weight: bold;
}
.comment a:hover {
	color: #333399;
}
</style>

<script>
function createXMLHttpRequest(){
	var xmlHttp = false;
	if (window.ActiveXObject){
		xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
	}
	else if (window.XMLHttpRequest){
		xmlHttp = new XMLHttpRequest();
	}
	else{
		alert("createXMLHttpRequest failure");
	}
	return xmlHttp;
}
	
function startRequest(id) {
	var xmlHttp = createXMLHttpRequest();
	xmlHttp.onreadystatechange = function() {
		if(xmlHttp.readyState == 4) {
			if(xmlHttp.status == 200 || xmlHttp.status == 0) {
				div_id = "comments_" + id;
				var comments = document.getElementById(div_id);
				var doc = xmlHttp.responseXML.getElementsByTagName("comments");
				if(doc[0]) {
					var results = doc[0].getElementsByTagName("comment");
				}
				else {
					//Here we need something to cater for IE.
				}
				var user, div, txt, url2 = null;
				for(var i=0; i<results.length; i++) {
					div  = document.createElement("div");
					user = document.createElement("a");
					txt  = document.createElement("p");
					time = document.createElement("p");
					comments.appendChild(div);
					div.appendChild(user);
					div.appendChild(txt);
					div.appendChild(time);
					div.setAttribute('id', "comment");
					div.className = "comment";
					var nodes = results[i].childNodes;
					url2 = "/viewprofile.php?user_id=" + (nodes[2].nodeValue || nodes[2].textContent || '#');
					user.setAttribute('href', url2);
					user.innerHTML = nodes[2].nodeValue || nodes[2].textContent || '-';
					txt.className = 'comment_text';
					txt.innerHTML = nodes[3].nodeValue || nodes[3].textContent || '-';
					time.setAttribute("id", "comment_time");
					time.innerHTML = nodes[4].nodeValue || nodes[4].textContent || '-';
				}
			}
		}
	};
//	var url = "/view_comment.php?parent_id=" + id;
	var url = "data.xml";//for local testing
	xmlHttp.open("GET", url, true);
	xmlHttp.send(null);
}

function makePropsList(obj, joinStr) {
//	alert(typeof obj);
	joinStr = (typeof joinStr==='undefined') ? '<br>' : joinStr;
	var a = [];
	for(var prop in obj) {
		a.push(prop + ': ' + obj[prop]);
	}
	return a.join(joinStr);
}


onload = function() {
	startRequest(0);
}
</script>
</head>

<body>

<h2>Comments</h2>
<div class="comments" id="comments_0"></div>

</body>
</html>

This works in FF and Opera but not in IE6, which steadfastly refuses to co-operate. Maybe you can test in later versions of IE (I can't with my LAN in its current condition).

Airshow

Thank you for the code. Right now I don't have a way to test out the code, but from looking at it, I'm confused at one part. What does the function makePropsList do? I don't see it referenced anywhere in the code.

pH,

I used makePropsList to explore object properties when developing the code and should have deleted it before posting.

Airshow

By the way, I also debugged my earlier jQuery code above and it successfully runs in FF, Opera and IE6.

I really think that jQuery is the way to go. I will post the debugged code if you are interested.

Airshow

Ahh, thanks very much Airshow. I used the code that you did and was able to view the comments with the static data. Instead of using the xml file, I just had the view_comment.php echo the xml data and it worked correctly. However, now that I'm trying to do it with the dynamically generated xml, it is not functioning correctly.

Here is the view_comment.php script. The GET variable is from the viewComment.js url which is in the first post.

<?php
	$parent_id = $_GET['parent_id'];
	
	$dbc = mysqli_connect(DB_HOST, DB_USER, DB_PASSWORD, DB_NAME);
	$comment_query = "SELECT * FROM comments WHERE parent_id = '$parent_id' ORDER BY post_time ASC";
	$comment_data = mysqli_query($dbc, $comment_query);
	$comment_rows = mysqli_fetch_array($comment_data);
	
	header('Content-Type: application/xml; charset=ISO-8859-1');
	xmlOutput = '<?xml version="1.0"?>';
	xmlOutput .= '<comments>';
	
	while($comment_rows){
		xmlOutput .= '<comment>';
		xmlOutput .= '<comment_id>'. $comment_rows['comment_id'] .'</comment_id>';
		xmlOutput .= '<poster_id>'. $comment_rows['poster_id'] . '</poster_id>';
		
		//Get username
		$username_query = "SELECT username FROM wwit_user WHERE user_id = '$comment_rows['poster_id']'";
		$username_data = mysqli_query($dbc, $username_query);
		$username_rows = mysqli_fetch_array($username_data);
		
		xmlOutput .= '<poster_name>'. $username_rows['username'] .'</poster_name>';
		xmlOutput .= '<comment_text>'. $comment_rows['comment_text'] .'</comment_text>';
		xmlOutput .= '<comment_time>'. $comment_rows['post_time'] .'</comment_time>';
		xmlOutput .= '</comment>';
	}
	xmlOutput .= '</comments>';
	header('Content-Type: application/xml; charset=ISO-8859-1');
	echo xmlOutput;
?>

I can't see anything glaringly obvious in the PHP except for two statements

header('Content-Type: application/xml; charset=ISO-8859-1');

The second should be deleted because headers must be set before any other output.

If that doesn't fix it, then maybe try asking in the PHP forum.

Airshow

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.