Become a MacRumors Supporter for $50/year with no ads, ability to filter front page stories, and private forums.

carlosbutler

macrumors 6502a
Original poster
Feb 24, 2008
691
2
i have started a music database with own templates, like itunes layout, wmp and so forth... anyways one of the things im trying to do is an options menu. and i want to make it so that you have a list of items, like a list you get from a form. which then updates another list on the side of it so that you are then finally able to open up a certain section. but what i was doing was create three iframes, with three functions (well more, but just for this lets say three) and each script updates each time something is clicked. so the script starts of writing <html><head><...> then the variable is something selected from the list. and i just cant get them to interact with each other.

just a quick mock up of what i have tried to get to work, but it just doesnt work (this has other random things which just let me see different things im trying to do in the future:

<html>
<head>
<title>Selection Thingy</title>
<script type='text/javascript'>
one=["one","uno","un","1"];
two=["two","dos","two in french","2"];
uno=["uno"];
un=["un"];
function firstbox(choice){
var s='<html><head></head><body>'
s+='<select size="7" name="select" onChange="secondbox(this.selectedIndex);" style="font-size:20px; width:100%; ">'
for(c=0;c < 4;c++)
s+='<option>'+one+'</option>'
s+='</select></form></body></html>'
with(document.getElementById('firstbox').contentDocument){
open();
write(s);
close();
}
}

function secondbox(choice){
if(choice==1){selection=one;}
if(choice==2){selection=two;}
var s="<html><head></head><body>";
s+="<form><select size='"+selection.length+"' >";
for(c=0;c<4;c++)
s+="<option>"+selection[c]+"</option>";
s+="</select></form></body></html>";
with(document.getElementById('secondbox').contentDocument){
open();
write(s);
close();
}
}
function toload(){
firstbox();
secondbox();
}

</script>
</head>
<body onload="javascript:toload()"><table width="1024" border="3">
<tr>
<td width="333"><iframe style="width:100%; height:300px" id="firstbox"></iframe></td>
<td width="332"><iframe style="width:100%; height:300px" id="secondbox"></iframe></td>
<td width="333"> </td>
</tr>
</table>
<table width="1024" border="3">
<tr>
<td> </td>
</tr>
</table>
</body>
</html>
 
Don't misuse iframes like this. It's totally unnecessary. Just use divs. I'll see if I can throw something together for you to reference. I looked around on Google, but couldn't find any code that explains this well to my own liking.
 
I put together a script that show how to do a dynamic list. I used my own list items so you'll need to make changes for it. This is really more of a reference piece than anything. I haven't heavily tested it. Only tested in Firefox and Safari. You can copy and paste the following into a new document and try it out. Let me know if you have questions.

HTML:
<?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>
<title>Dynamic Lists</title>
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
<script type="text/javascript">

DynoList = function() {
  var lists = new Array();
  lists['Colors'] = new Array('Red', 'Blue', 'Green');
    lists['Red'] = new Array('Blood', 'Cherry', 'Rose');
    lists['Blue'] = new Array('Ocean', 'Jeans', 'Navy');
    lists['Green'] = new Array('Forest', 'Grass', 'Frog');
  lists['Shapes'] = new Array('Circle', 'Square', 'Diamond');

  Init = function() {
    // Add event handlers for selection changes
    document.getElementById('box1').onchange = function(){Dyn(this.value,2);};
    document.getElementById('box2').onchange = function(){Dyn(this.value,3);};
    // Set boxes for initial load
    if (document.getElementById('box1')) {
      Dyn(document.getElementById('box1').value,2);
    }
    // Default to the color option
    else { Dyn('Colors',2); }
  };
  Dyn = function(choice, box) {
    // Check if there was a valid choice made
    if (!lists[choice]) {
      if (document.getElementById('box'+box)) {
        document.getElementById('box'+box).innerHTML =
          '<option value="">Pick prev first<\/option>';
        Dyn(document.getElementById('box'+box).value, box+1);
      }
      return;
    }
    // Create list elements
    var list = "";
    for (var a=0, b=lists[choice].length; a<b; a++) {
      list += "<option value='"+ lists[choice][a] +"'>"+ lists[choice][a] +"<\/option>\n";
    }
    // Display lists elements
    document.getElementById('box'+box).innerHTML = list;
    // Set next box in case it needs it
    Dyn(document.getElementById('box'+box).value, box+1);
  };
  appendOnLoad = function(fx) {
    var old = window.onload;
    if (typeof old != 'function') { window.onload = fx; }
    else { window.onload = function() { old(); fx(); } }
  };
  appendOnLoad(Init);
}();

</script>
</head>
<body>
<select id="box1">
  <option value="">Choose</option>
  <option value="Colors">Colors</option>
  <option value="Shapes">Shapes</option>
</select>
<select id="box2">
  <option value="">Pick prev first</option>
</select>
<select id="box3">
  <option value="">Pick prev first</option>
</select>
</body>
</html>
 
yes just two questions
1) how did you do that soo quickly :p - ive only just started of javascript with tutorials and such

2) the actual questions, if i have another document with lists of things, such as an XML file (thats all i can think off) how would i be able to get the values to show up in the lists, but more importantly actually be lined up - ie in your example you had colours --> blue --> ocean

thanks again for all the help
 
yes just two questions
1) how did you do that soo quickly :p - ive only just started of javascript with tutorials and such

2) the actual questions, if i have another document with lists of things, such as an XML file (thats all i can think off) how would i be able to get the values to show up in the lists, but more importantly actually be lined up - ie in your example you had colours --> blue --> ocean

thanks again for all the help

1.) I like JavaScript and have created a number of scripts and after a while they start to feel similar so it just comes together pretty quick. I've also been starting to use the same format so it almost feels like filling in the blanks.

2.) See this page on some simple examples of reading in an XML file and parsing it. It's hard to give much of an answer here unless I know what the XML looks like. Is there any reason to use an XML file and not just place it in the JavaScript like my example. Just want to understand where you're coming from so I can give advice accordingly. It'll likely end up looking like nested for loops though.
 
Sorry to get back so late, was doing some work.

Essentially its a music file, with tags

<albums>
<album>
<artwork>whatever.jpg</artwork>
<title>Album Title</title>
<artist>An artist</artist>
<track>
<title>song 1</title>
<mp3>song1.mp3</mp3>
</track>
</album>
</albums>
and i cant have it in as part of the code because there is way too much. these xml sheets will be generated and then uploaded to the server so it needs to be dynamic and pick everything from one song to thousands of songs. so to get it done with artist in one selection and then album in the second.

EDIT: better still forget the artist, i will work that out my self. only need album
 
Just a suggestion: if your XML format is not set yet, you may want to consider using attributes for some of the properties.

For instance, it may make a bit more sense to have this:

HTML:
<albums>
    <album title = "Album Title" artist = "An Artist">
        <track title="song 1" mp3 = "song1.mp3" />
    </album>
</albums>

Generally, it is better to organize fields that are only allowed to occur once as attributes, and ones that may appear more than once as elements. This way, the XML looks more concise and is more meaningful.
 
OK, I put together a new example that works from a XML file to generate the lists. As before, you can copy and paste this into a new file and try it out. After the HTML I'm listing the practice XML I used specifically for reference. Currently the JavaScript is expecting the XML file to be named "items.xml," but you can change that in the JavaScript near the top.

So the example is set so that the first box list the album names, and the second box is the song titles for that album. At this point there was no third box, but you may add an artist box that would likely go before the album box, but you can decide on that.

You should also consider what CoreWeb mentioned above if it's within your power, but the example here assumes you're using the previous XML format. It could be updated for a different XML format.

HTML:
<?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>
<title>Dynamic Lists</title>
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
<script type="text/javascript">

DynoList = function() {
  var xmlFile = 'items.xml';
  var lists = new Array();   // master list
  var albums = new Array();  // for album names

  Init = function() {
    // Add event handlers for selection changes
    document.getElementById('box1').onchange = function(){Dyn(this.value,2);};
    // Load up the xml
    LoadXML(xmlFile);
    // Set box 1
    var list = "<option value=''>Choose<\/option>\n";
    for (var a=0, b=albums.length; a<b; a++) {
      list += "<option value='"+ albums[a] +"'>"+ albums[a] +"<\/option>\n";
    }
    // Display lists elements
    document.getElementById('box1').innerHTML = list;
    // Set boxes for initial load
    if (document.getElementById('box1')) {
      Dyn(document.getElementById('box1').value,2);
    }
  };
  Dyn = function(choice, box) {
    // Check if there was a valid choice made
    if (!lists[choice]) {
      if (document.getElementById('box'+box)) {
        document.getElementById('box'+box).innerHTML =
          '<option value="">Pick prev first<\/option>';
        Dyn(document.getElementById('box'+box).value, box+1);
      }
      return;
    }
    // Create list elements
    var list = "";
    for (var a=0, b=lists[choice].length; a<b; a++) {
      list += "<option value='"+ lists[choice][a] +"'>"+ lists[choice][a] +"<\/option>\n";
    }
    // Display lists elements
    document.getElementById('box'+box).innerHTML = list;
    // Set next box in case it needs it
    Dyn(document.getElementById('box'+box).value, box+1);
  };
  LoadXML = function(file) {
    var xmlDoc;
    try { xmlDoc = new ActiveXObject("Microsoft.XMLDOM"); }
    catch(e) {
      try { xmlDoc = document.implementation.createDocument('','',null); }
      catch(e) { alert("Problem accessing XML: "+ e); }
    }
    xmlDoc.async = false;
    xmlDoc.load(file);
    // Create array from XML
    var album = xmlDoc.getElementsByTagName('album');
    for (var a=0, b=album.length; a<b; a++) {
      var titles = album[a].getElementsByTagName('title');
      var albumName = "";
      albumName = titles[0].childNodes[0].nodeValue;
      // keep list of album names
      albums[a] = albumName;
      lists[albumName] = new Array();
      // Grab all of the track titles for album
      for (var c=1, d=titles.length; c<d; c++) {
        lists[albumName][c-1] = titles[c].childNodes[0].nodeValue;
      }
    }
  };
  appendOnLoad = function(fx) {
    var old = window.onload;
    if (typeof old != 'function') { window.onload = fx; }
    else { window.onload = function() { old(); fx(); } }
  };
  appendOnLoad(Init);
}();

</script>
</head>
<body>
<select id="box1">
  <option value="">Need JS Enabled</option>
</select>
<select id="box2">
  <option value="">Pick prev first</option>
</select>
</body>
</html>
items.xml:
HTML:
<?xml version="1.0" encoding="utf-8"?>
<albums>
<album>
  <artwork>whatever.jpg</artwork>
  <title>Album Title 1</title>
  <artist>An artist</artist>
  <track>
  <title>song 1</title>
  <mp3>song1.mp3</mp3>
  </track>
  <track>
  <title>song 2</title>
  <mp3>song2.mp3</mp3>
  </track>
  <track>
  <title>song 3</title>
  <mp3>song3.mp3</mp3>
  </track>
</album>
<album>
  <artwork>what.jpg</artwork>
  <title>Album Title 2</title>
  <artist>Second artist</artist>
  <track>
  <title>song 6</title>
  <mp3>song6.mp3</mp3>
  </track>
  <track>
  <title>song 8</title>
  <mp3>song8.mp3</mp3>
  </track>
  <track>
  <title>song 9</title>
  <mp3>song9.mp3</mp3>
  </track>
</album>
</albums>
 
sorry its taken me so long to get back. so far thanks for all the help, although i see you have used childNodes and nodeValue.

i dont really understand what they are, although i am going to be looking over tutorials and teaching books since they are obviously quite useful.

is there a way of doing the getting of the XML without using nodes?
 
is there a way of doing the getting of the XML without using nodes?

XML is made of nodes. It would be like creating a web page without tags. Why is using nodes a problem, they're just tags for the most part?

For something like,
Code:
titles[0].childNodes[0].nodeValue;
titles[0] is a title tag in the XML.
childNodes[0] is the text node inside the given tag.
nodeValue is the actual text inside the text node.

Here's a good resource for learning the DOM and manipulating it with JavaScript.
 
Just a suggestion: if your XML format is not set yet, you may want to consider using attributes for some of the properties.

For instance, it may make a bit more sense to have this:

HTML:
<albums>
    <album title = "Album Title" artist = "An Artist">
        <track title="song 1" mp3 = "song1.mp3" />
    </album>
</albums>
Generally, it is better to organize fields that are only allowed to occur once as attributes, and ones that may appear more than once as elements. This way, the XML looks more concise and is more meaningful.

Using your example, albums in the real world have multiple tracks, so that would be (simplified example with 3 songs per album):

Code:
<?xml version="1.0" ?> 
<albums>
    <album title = "Album Title" artist = "An Artist">
        <track title="song 1" mp3 = "song1.mp3" />
        <track title="song 2" mp3 = "song2.mp3" />
        <track title="song 3" mp3 = "song3.mp3" />
    </album>
</albums>

-jim
 
ah right did not read that, well to be honest nothing on it since im quite busy but thanks for the pointer
 
Register on MacRumors! This sidebar will go away, and you'll see fewer ads.