Hi,
I have a site which lists the basic information of CDs and allows the user to click a link to see detailed information regarding each CD. I've been doing that for a long time by just putting the detailed information in a DIV and using a script to toggle the visibility of that DIV. Unfortunately, I've reached the point where that bloats the page too much for it to load efficiently.

My idea is to use an AJAX call and simply load the detailed information from an external file whenever the user clicks the link. This is basically the code I've tried to use for that, but using it would require me to individually assign an ID to every DIV, which is unreasonable.

I've kicked around various ideas--making a similarly-functioning code that applies to classes instead, using a script to apply an ID to an element when it is clicked and then calling the external page into that, etc.--but none of them have worked out.

Can anyone give some specific answers to this problem or even help me think of it from a different angle?

Recommended Answers

All 8 Replies

Here's something that you can work with, tested in ie6+ and opera9.
This is the code for the (x)HTML document, all codes is as follows:

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
   "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="X-UA-Compatible" content="IE=EmulateIE7" />
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta http-equiv="Content-Style-Type" content="text/css" />
<meta http-equiv="Content-Script-Type" content="text/javascript" />
<title>AJAX Demo</title>
<style type="text/css">
table {
   border : none;
   border-collapse : collapse;
   margin : 1em 0em 1em 0em;
   text-align: left;
   width: auto; }

td, th {
   padding: .200em 1em .200em 1em;
   border-bottom: 1px solid #ccc;
   vertical-align : middle;
   width: auto; }
legend {
    background-color: #f2f2f2;
    padding: .250em 1em .250em 1em;
    border: 1px solid;
    margin-left: 1em; }

fieldset {
   background-color: #eee;
   border: 1px solid;
   color: #405060;
   text-align: left; }

</style>
<script type="text/javascript">
/* <![CDATA[ */

var cdInfo, cdtitle, artist, album, price, description, handle;

function details( ids ) {

/* if you are working on-line then you will need to remove  un-comment the statement provided below ( vise versa ) */

/*
   if ( cdInfo.readyState !== 400 ) return;
   if ( cdInfo.status !== 200 ) {
      alert("\nUnable to parse XML data!");
   } */// This is a commented statement and should be romoved if you ar working online -

album = cdInfo.responseXML.getElementsByTagName("album")[0];
cdtitle = album.getElementsByTagName("title")[ids];
artist = album.getElementsByTagName("artist")[ids];
price = album.getElementsByTagName("price")[ids];
description = album.getElementsByTagName("description")[ids];
handle = ( document.getElementById ) ? document.getElementById("loadData") : document.all.loadData;
   if ( handle ) {
      try {
      data = '<fieldset><legend>' +  artist.firstChild.nodeValue + '</legend>\n';
      data += '<table summary="Album Details">\n';
      data += '<tr>\n';
      data += '<th>Title: </th>\n';
      data += '<td>' + cdtitle.firstChild.nodeValue + '</td>\n';
      data += '</tr>';
      data += '<tr>\n';
      data += '<th>Artist: </th>\n';
      data += '<td>' + artist.firstChild.nodeValue + '</td>\n';
      data += '</tr>\n';
      data += '<tr>\n';
      data += '<th>Price: </th>\n';
      data += '<td>' + price.getAttribute("amount") + '</td>\n';
      data += '</tr>\n';
      data += '<tr>\n';
      data += '<th>Details: </th>\n';
      data += '<td>' + description.firstChild.nodeValue + '</td>\n';
      data += '</tr>\n';
      data += '</table>\n';
      data += '</fieldset>\n';
      handle.innerHTML = data;
      } catch(e) { }
   } 
}


function loadCdData( url, ids ) {
cdInfo = null;
   if ( window.XMLHttpRequest ) {
         cdInfo = new XMLHttpRequest();
   } else if ( window.ActiveXObject ) {
      try {
          cdInfo = new ActiveXObject("Msxml2.XMLHTTP");
      } catch( e ) {
          cdInfo = new ActiveXObject("Microsoft.XMLHTTP");
      }
   }
   if ( cdInfo !== null ) {
      cdInfo.onreadystatechange = function() { 
   try { 
      details( ids ); 
   } catch( error ) {
      details( ids );
   }
}; 
      cdInfo.open("GET", url, true);
      cdInfo.send( null );
   } else {
      alert("\nYour browser does not support AJAX Request!"); 
   }
}

/* ]]> */
</script>
</head>
<body>
<div id="loadData">

</div>
<p>Now let's make some request for <a href="javascript:void(0);" id="mariah0" onclick="loadCdData('music.xml', 0);">Mariah Carey's</a> cd details or <a href="javascript:void(0);" id="john0" onclick="loadCdData('music.xml', 1);">John Mayer's</a> album!</p>
</body>
</html>

and the code for the music.xml:

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE album [
<!ELEMENT album (cd)*>
<!ELEMENT cd (title, artist, price, description)>
<!ELEMENT title (#PCDATA)>
<!ELEMENT price EMPTY>
<!ATTLIST price
   id ID #IMPLIED
   amount CDATA "$0.00">
<!ELEMENT artist (#PCDATA)>
<!ATTLIST artist
   genre (rnb|rock|pop|jazz) "jazz">
<!ELEMENT description (#PCDATA|br)*>
<!ELEMENT br EMPTY>
<!ENTITY ap "&apos;">
]>
<album>

<!-- This should have some list of track's for every artist. But lets just concentrate on the 4 needed details when we are buying cds (title artist, price and details).

Created by : essential 

(c) 2008 essential works.

This is a well formed XML document with valid dtd.  --> 

<cd>
<title>Emancipation of MIMI</title>
<artist>Mariah Carey</artist>
<price amount="$4.25" />
<description>Some detailed information about "Mariah Carey&ap;s" cd&ap;s...</description>
</cd>

<cd>
<title>Room for Squares</title>
<artist>Jonh Mayer</artist>
<price amount="$4.00" />
<description>Some detailed information about "Jonh Mayer&ap;s" cd&ap;s...</description>
</cd>
</album>

I've forgot to add an else { // statement } in the details() function. Just fairly add one and trap those conditions inside a try...catch() statement.

You can store all information you need in the music.xml document and add a few more elements for easy ajax call. Hope it helps and good day to you...

Thank you, that will definitely be helpful. However, I'm not sure that it really solves my initial problem.

I probably stated it in a confusing way, but my main problem is that I don't want to manually assign an ID to every DIV that information will be shown in. But I just haven't seen an example of AJAX usage that doesn't involve using an ID.

On the 1st version- elements don't actually require any ids. But a pointer n0. needed to be stated on each link, with the onclick event's for call back function. Unfortunately, it requires alot of work and incorporate the callbacks on each link. In other words you must specify the loadCdData('music.xml', 0) on the first link, loadCdData('music.xml', 1) which goes on 2nd link, and so on...
But on this moded version, the only thing it requires is a base element that holds the entire links. For example:

<div id="listed"><!-- as the element -->
<a href="#">Link 1 or Artist 1</a>
<a href="#">Link 2 or Artist 2</a><!-- and so on... -->
</div>

the id of the base element must be specified on baseCount variable. And that's all it need to skip the whole work that you are stating on this current issue.
All codes is as follows:

Moded Version

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
   "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="X-UA-Compatible" content="IE=EmulateIE7" />
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta http-equiv="Content-Style-Type" content="text/css" />
<meta http-equiv="Content-Script-Type" content="text/javascript" />
<title>AJAX Demo</title>
<style type="text/css">
table {
   border : none;
   border-collapse : collapse;
   margin : 1em 0em 1em 0em;
   text-align: left;
   width: auto; }

td, th {
   padding: .200em 1em .200em 1em;
   border-bottom: 1px solid #ccc;
   vertical-align : middle;
   width: auto; }
legend {
    background-color: #f2f2f2;
    padding: .250em 1em .250em 1em;
    border: 1px solid;
    margin-left: 1em; }

div { margin: 0 auto 2em auto; width: 100%; }

fieldset {
   background-color: #eee;
   border: 1px solid;
   color: #405060;
   text-align: left; }

</style>
<script type="text/javascript">
// <![CDATA[ 
var cdInfo, cdtitle, artist, album, price, description, handle;
var baseCount, isAnchor, numId;

function details( ids ) {

/* if you are working on-line then you will need to remove  un-comment the statement provided below ( vise versa ) */

/*
   if ( cdInfo.readyState !== 400 ) return;
   if ( cdInfo.status !== 200 ) {
      alert("\nUnable to parse XML data!");
   } */// This is a commented statement and should be romoved if you ar working online -

album = cdInfo.responseXML.getElementsByTagName("album")[0];
cdtitle = album.getElementsByTagName("title")[ids];
artist = album.getElementsByTagName("artist")[ids];
price = album.getElementsByTagName("price")[ids];
description = album.getElementsByTagName("description")[ids];
handle = ( document.getElementById ) ? document.getElementById("loadData") : document.all.loadData;
   if ( handle ) {
      try {
      data = '<fieldset><legend>' +  artist.firstChild.nodeValue + '</legend>\n';
      data += '<table summary="Album Details">\n';
      data += '<tr>\n';
      data += '<th>Title: </th>\n';
      data += '<td>' + cdtitle.firstChild.nodeValue + '</td>\n';
      data += '</tr>';
      data += '<tr>\n';
      data += '<th>Artist: </th>\n';
      data += '<td>' + artist.firstChild.nodeValue + '</td>\n';
      data += '</tr>\n';
      data += '<tr>\n';
      data += '<th>Price: </th>\n';
      data += '<td>' + price.getAttribute("amount") + '</td>\n';
      data += '</tr>\n';
      data += '<tr>\n';
      data += '<th>Details: </th>\n';
      data += '<td>' + description.firstChild.nodeValue + '</td>\n';
      data += '</tr>\n';
      data += '</table>\n';
      data += '</fieldset>\n';
      handle.innerHTML = data;
      } catch(e) { }
   } 
}


function loadCdData( url, ids ) {
cdInfo = null;
   if ( window.XMLHttpRequest ) {
         cdInfo = new XMLHttpRequest();
   } else if ( window.ActiveXObject ) {
      try {
          cdInfo = new ActiveXObject("Msxml2.XMLHTTP");
      } catch( e ) {
          cdInfo = new ActiveXObject("Microsoft.XMLHTTP");
      }
   }
   if ( cdInfo !== null ) {
      cdInfo.onreadystatechange = function() { 
   try { 
      details( ids ); 
   } catch( error ) {
      details( ids );
   }
}; 
      cdInfo.open("GET", url, true);
      cdInfo.send( null );
   } else {
      alert("\nYour browser does not support AJAX Request!"); 
   }
} 
var isInfo = function( elem ) {
elem = elem ? elem : window.event;
t = elem.target ? elem.target : elem.srcElement;
baseCount = ( document.getElementById ) ? document.getElementById("listed") : document.all.listed;
   if (( t.nodeName.toLowerCase() === "a" )  && ( t.parentNode.id === "listed" )) {
   if ( t.sourceIndex ) {
     try { // This is way too easy than performing a loop!
          // The only issue here is, (that not all browser support this type indexing feature).
     ids = (( t.sourceIndex - baseCount.sourceIndex ) -1 );
     } catch( error ) { alert("Unsupported feature!\nPlease update your browser!");  
     } 
loadCdData("music.xml", ids); 
   }  
   else { // If those things from above didn't work -
          // Then let's perform a loop to get it done.
      try {
      isAnchor = baseCount.getElementsByTagName("a");
      for ( var i = 0; i < isAnchor.length; i++ ) {
// Assigning dynamic ids --
isAnchor[i].id = ( "anch" + i );
      } ids = parseInt(t.id.match(/\d/g));
loadCdData("music.xml", ids);
      } catch( error ) {
        alert("Get rid of these browser!");
      }
    }    
  }
}; // Force to load XML data without specifying any reference to the XMLHttpRequest Handler -
if (window.addEventListener)
window.addEventListener("click",isInfo,false);
else if (window.attachEvent)
window.attachEvent("onclick",isInfo);
else      
document.onclick = isInfo; 
// ]]>
</script>
</head>
<body>
<div id="loadData">
<a href="javascript:void(0);">dummy link wil not output!</a>
</div>
<div id="listed">Now let's make some request for <a href="javascript:void(0);">Mariah Carey's</a> cd details or <a href="javascript:void(0);">John Mayer's</a> album!</div>
</body>
</html>

NOTE that when you add new artist or a link on the base element collections, you also need to specify the details for the new artist in the music.xml collections. Just like Mariah and John.

This is extremely helpful. I have one more question though, if that's alright.

Say, for instance, I have the following code:

<div id="loadData">Data will load here...</div>

<div id="listed">
<a href="">Mariah</a>
<a href="">John</a>
<a href="">Someone Else</a>
</div>

Is there a way that I could keep one of the links in the DIV from calling content? For example, if I put a link to discovery.com right after the Mariah link, I suppose it will be recognized as "loadCdData('music.xml', 1)." Is there a way to prevent this on certain links, so that I can put them within the same DIV without them calling content from the XML file?

(P.S., thank you very much! You have been extremely helpful, and I've learned quite a few things just by working with this issue. I will definitely be using some of these techniques in the future. It's much appreciated!)

Yes it can be prevented by simply adding this to the following lines:
first add this on line #43

var isLink = /javascript\:/;

then from line #121 after the ids declaration &#8212; add this line:

t = ( isLink.test( t.href ) ) ? loadCdData("music.xml", ids ) : alert( ids );

and remove line #124 then replace line #134 with the same line that we have just provided in line #121.
This changes will output an alert of the current index position of the clicked anchor, if the pattern do not match. Else loadCdData() will be initialized.

t = ( isLink.test( t.href ) ) ? loadCdData("music.xml", ids ) : alert( ids );
// all instance will take effect on this portion.
// just be sure to provide the statement that will suit your needs.

Try to test it by adding new links after john or you can totally remove the links which is currently stated on this demo, if you only need this function for indexing reference.
TEST:

<div id="listed">Now let's make some request for <a href="javascript:void(0);">Mariah Carey's</a> cd details or <a href="javascript:void(0);">John Mayer's</a> album! <a href="#">Dummy1</a> 
<a href="#">Dummy2</a>
<a href="#">Dummy3</a></div>

hope everything is clear now. Good day...

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.