Hi,

I'm not really a programmer, but have been tasked with performing some AJAX functions to make a call and return results to my page using getElementByID. I have been able to return search results to the page, but now need to make them clickable as it will lead to another query. E.g., when a user clicks one of the returned categories, it should invoke a query to return products within that category.

Right now, I just want to see how to effectively wrap an HREF around each search result.

Here's the page I'm working on:
http://empress-media.net/jimflynnrentals/gear.html

Here's the javascript I used to return the results to that DIV:

function setDataHTML(xmlHttp)
{

	document.getElementById('CollapsiblePanel2').lastChild.innerHTML = xmlHttp.responseText;

}

Any suggestions on how to make these results clickable?

Thanks!

Within your chosen methodology, you have two basic choices; server-side-heavy vs client-side-heavy.

The server-side-heavy solution involves building valid html string(s) at the server and returning it/them in the xmlHttp.responseText.

In the client-side-heavy solution you would return the the component strings (eg. href, image src, text), in the xmlHttp.responseText then use them either to to compose the required HTML string, or to build html elements using DOM methods.

In either case some javascript is necessary to insert the composed html/element into the document.

For the client-side-heavy solution with DOM metods, you might use something like the code below:

function insertLink(href, inner, containerID){
	var a = document.createElement('a');
	a.href = href;
	if (typeof inner == 'string') { a.innerHTML = inner; }
	else if (typeof inner == 'object') { a.appendChild(inner); }
	var container = (document.getElementById) ? document.getElementById(containerID) : document.all[containerID];
	if(container) { container.appendChild(a); }
}

The point of insertion needs to already exist on the page before the function is called or it won't work. Therefore to test it call as follows:

onload = function(){
	insertLink('http:\/\/www.daniweb.com', 'Daniweb', 'myContainer');

	var domImg = document.createElement('img');
	domImg.setAttribute('src', 'http:\/\/www.daniweb.com/alphaimages/logo/logo.gif');
	domImg.setAttribute('border', 0);
	insertLink('http:\/\/www.daniweb.com', domImg, 'myContainer2');
}

with the following HTML

<body>
<div id="myContainer"></div>
<div id="myContainer2"></div>
</body>

Those are the basics. It can get more involved if you want further features.

In your case you may need to loop through and or parse out your xmlHttp.responseText to find the href/src/text, and maybe you will need an outer loop to handle multiple products.

Airshow

Thanks! I think I'm getting closer. I am now getting all of my search results wrapped in the same HREF, so all results are now 1 hyperlink. (See http://empress-media.net/jimflynnrentals/gear.html). My next step is to somehow make them separate links.

Here's what I have now.

function insertLink(href, inner, containerID){
	var a = document.createElement('a');
	a.href = href;
	if (typeof inner == 'string') { 
		a.innerHTML = inner; 
		}
		else if (typeof inner == 'object') 
		{ 
		a.appendChild(inner); }
	var container = (document.getElementById('CollapsiblePanel2'));
	if(container) { container.appendChild(a); }
}


onload = function(){
	var domImg = document.createElement('href');
	domImg.setAttribute('href', 'http:\/\/empress-media.net/jimflynnrentals');
	insertLink('http:\/\/empress-media.net/jimflynnrentals', domImg, 'CollapsiblePanel2');
}

Any suggestions are hugely appreciated!

~Maile

Maile,

You might like to try something slightly different. I think it would suit your application. It involves cloning a hidden HTML "prototype", then populating the clones with particular attributes. This has the advantage of allowing you to develop the appearance of the prototype in HTML, which is much friendlier than using DOM statements in javascript.

I have created a sample array of objects to simulate your HTTPRequest.response(s), to give the code some data to act on.
You should be able to adapt it to your actual application.

<!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">
.cPanel { margin:0 0 6px 0; }
.cPanel img { border:1px solid #333333; }
.cPanel p { margin:0; color:#660000; font-size:9pt; }
.cPanel a { color:#660000; text-decoration:none; }
.cPanel a:hover { color:#cc0000; text-decoration:underline; }
</style>

<script>
var prductsInCategory = [
	{href:'http:\/\/empress-media.net/jimflynnrentals', imgSrc:'http:\/\/empress-media.net/jimflynnrentals/images/003R_angle.jpg', title:'Product A'},
	{href:'http:\/\/empress-media.net/jimflynnrentals', imgSrc:'http:\/\/empress-media.net/jimflynnrentals/images/003R_angle.jpg', title:'Product B'},
	{href:'http:\/\/empress-media.net/jimflynnrentals', imgSrc:'http:\/\/empress-media.net/jimflynnrentals/images/003R_angle.jpg', title:'Product C'},
	{href:'http:\/\/empress-media.net/jimflynnrentals', imgSrc:'http:\/\/empress-media.net/jimflynnrentals/images/003R_angle.jpg', title:'Product D'}
];
onload = function(){
	for(var i=0; i<prductsInCategory.length; i++) {
		var container = (document.getElementById) ? document.getElementById('collapsiblePanels') : document.all['collapsiblePanels'];
		var proto = (document.getElementById) ? container.document.getElementById('collapsiblePanelProtoWrapper') : document.all['collapsiblePanelProtoWrapper'];
		var cPanel = proto.cloneNode(true);//This line clones hidden the prototype
		var img = cPanel.document.getElementById('collapsiblePanelProtoImg');
		var a1 = cPanel.document.getElementById('collapsiblePanelProtoLink1');
		var a2 = cPanel.document.getElementById('collapsiblePanelProtoLink2');
		var txt = cPanel.document.getElementById('collapsiblePanelProtoTxt');
		//Set ids
		cPanel.setAttribute('id', 'cPanel'+i);
		img.setAttribute('id', 'cPanelImg'+i);
		a1.setAttribute('id', 'cPanelLink1'+i);
		a2.setAttribute('id', 'cPanelLink2'+i);
		txt.setAttribute('id', 'cPanelTxt'+i);
		//Set other attribs
		cPanel.style.display = 'block';//Show the clone
		img.setAttribute('src', prductsInCategory[i].imgSrc);
		a1.setAttribute('href', prductsInCategory[i].href);
		a2.setAttribute('href', prductsInCategory[i].href);
		a2.innerHTML = prductsInCategory[i].title;
		container.appendChild(cPanel);
	}
}
</script>
</head>

<body>

<div id="collapsiblePanels">
	<div class="cPanel" id="collapsiblePanelProtoWrapper" style="display:none;">
		<a id="collapsiblePanelProtoLink1" href=""><img id="collapsiblePanelProtoImg" src="http://empress-media.net/jimflynnrentals/images/003R_angle.jpg" border="0"></a>
		<p id="collapsiblePanelProtoTxt"><a id="collapsiblePanelProtoLink2" href="">Product title</a><p>
	</div>
</div>

</body>
</html>

Must rush ..... real work beckons.

Airshow

Sorry for the late response, I got pulled on to another project for a little while. Thanks Airshow - you were very comprehensive! I apologize though, I feel like I pointed you to the wrong point in my page. I uploaded a new page that only has the piece I'm working on so as to eliminate confusion (I will try what you suggested though when I get to that point in the development!).

Here's the link: http://empress-media.net/jimflynnrentals/gear_test.html

Each of the categories (Accessories, Audio Equipment, Audio Recorders...) is returned as static text right now and I would like to make those clickable (my original post shows how I get them on the page). Eventually, click any of these items would lead to a subquery of stock within that category.

Would it be better to output these results into individual cells within a table and add an HREF around each result? My weakness is syntax, so any help is much appreciated!

Thanks again,
Maile

Maile,

I've re-read your first post and think I understand better now.

A good way to build a list is to use a <ul>. There's a lot of flexibility in CSS to style a <ul> and its <li>s, so maybe you could populate your CollapsiblePanelContent divs with something like this (hard-coded):

<style type="text/css">
ul.panelList { margin:0; padding:0; list-style-type:none; }
ul.panelList li { margin:0; padding:0 0 0 5px; background-image: none; list-style-type:none; }
ul.panelList a { color:#c0c0c0; text-decoration:none; }
ul.panelList a:hover { color:#999999; }
</style>
<ul id="panelList2" class="panelList">
<li><a href="#">Accessories</a></li>
<li><a href="#">Audio Equipment</a></li>
<li><a href="#">Audio Recorders</a></li>
<li><a href="#">Computers</a></li>
<li><a href="#">Miscellaneous</a></li>
<li><a href="#">SALES</a></li>
<li><a href="#">Video Equipment</a></li>
</ul>

OK, so that was hard-coded. Now, to get the <li>s into the <ul> you have a couple of basic choices:

Method 1:
As the hard-coded version above but with an empty <ul id="panelList2" class="panelList"></ul> . Server-side, build strings of the format <li><a href="#">Accessories</a></li> and return them AJAX-wise, then successively insert them into the document with document.getElementById('panelList2').innerHTML = xmlHttp.responseText; .

Method 2:
I'm not sure what flexibility you have in setting properties of the returned xmlHttp object but this is an idea.
As the hard-coded version above but with an empty <ul id="panelList2" class="panelList"></ul> . Server-side, arrange for each returned xmlHttp object to have the following properties:

  • xmlHttp.linkHREF
  • xmlHttp.linkTxt

Now build a link and insert it into the document with:

var li = document.createElement('li');
var a = document.createElement('a');
a.href = xmlHttp.linkHREF;
a.innerHTML = xmlHttp.linkTxt;
li.appendChild(a);
document.getElementById('panelList2').appendChild(li);

Method 1 is probably easier, but method 2 would be more fun.

Of course, whichever method you choose, you still need to devise the hrefs to give the links their required actions.

Let us know how you get on with it.

Airshow

Okay, I feel very confident that this is the right path (I'm opting for method 2 now). However, I'm overly tired and think my brain is missing something so I will give it another go in the morning. What I did so far is to add the following to my DIV where the results should display:

<ul id="panelList2" class="panelList"></ul>

I also added the JS syntax as you suggested. When I run the page, I get an error that: "document.getElementById(...) is null or not an object"

As for your statement:

Server-side, arrange for each returned xmlHttp object to have the following properties:

  • xmlHttp.linkHREF
  • xmlHttp.linkTxt

Are you referring to using something such as PHP to set these properties?

Thanks again for all of your help!
Maile

Maile,

I confess I have completely lost my train of thought on this one but will try to answer your questions.

I also added the JS syntax as you suggested. When I run the page, I get an error that: "document.getElementById(...) is null or not an object"

The statement needs to go in the right place. Remember that document.getElementById(...) will only find elements once the page has loaded. My block of code that includes document.getElementById('panelList2')... is designed to go in an AJAX callback function. It certainly won't work in javascript's global scope.

Are you referring to using something such as PHP to set these properties?

Exactly so. From your original post I understand that you are using AJAX, so must be running PHP or similar server-side.

The professional approach to communicating variables and objects between client and server is to use something called JSON. Google it to find out more. Assuming you are not using JSON then you can adopt a DIY approach by which you convert server-side (PHP) data into a single string that is returned as the response to the xmlHttp object client-side. This is pretty well all JSON or any other method does, because an HTTP request only ever returns a string data (albeit rather well structured). In that light, a DIY approach is not really so DIY as some might have you believe.

I have just had a play on my development computer (Apache with PHP) and came up with the something like what you might want, but remembering that I've lost my way on your problem somewhat. I think the solution is actually a hybrid of my "Method 1" and "Method 2" but should be comprehensive enough for you to see how your data might be delivered in string form by the server and built by javascript onto clickable links. See attachment.

Airshow

Thanks! I will give it a go and let you know. I will likely work this in phases (to better understand each step) to eventually incorporate it into the full dynamic functionality I need.

This article has been dead for over six months. Start a new discussion instead.