Arrays in JavaScript [SOLVED]

Hi,
I am trying to create a drop down menu which links to another dropdwon menu.

I can run a simple version of this from javascript I found on the the net and it works fine, like this,

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html dir="ltr" lang="en">
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"> 
    <title>Dynamic Select Boxes example</title>
    <style type="text/css">
    </style>
    <script type="text/javascript">
        function populate(o)
        {
            d=document.getElementById('de');
            if(!d){return;}            
            var mitems=new Array();
            mitems['topic1']=['subtopic1','subtopic2'];
            mitems['topic2']=['subtopic3','subtopic4'];
            d.options.length=0;
            cur=mitems[o.options[o.selectedIndex].value];
            if(!cur){return;}
            d.options.length=cur.length;
            for(var i=0;i<cur.length;i++)
            {
                d.options[i].text=cur[i];
                d.options[i].value=cur[i];
            }
        }
    </script>
</head>
</html>

I have a table of topics and subtopic which are linked by the ‘id’ field in the ‘topics’ table being the same as the ‘topicid’ field in the ‘subtopics’ table. So each topic has subtopics associated with it.
I am trying to create a pulldown menu of topics which when clicked displays another pulldown menu of only the subtopics associated with that topic.
The lines to do that in the javascript above are,

            mitems['topic1']=['subtopic1','subtopic2'];
            mitems['topic2']=['subtopic3','subtopic4'];

But how do I adapt this for my purpose? The tables look like this for ‘topics’

and for ‘subtopics’

I build the $topics array like this,

<?php
  include $_SERVER['DOCUMENT_ROOT'] . '/artgibney/includes/db.inc.php';

  // Build the list of topic rows
  try
  {
    $result = $pdo->query('SELECT id, topic FROM topics');
  }
  catch (PDOException $e)
  {
    $error = 'Error fetching list of topics.';
    include 'error.html.php';
    echo $e;
    exit();
  }

  foreach ($result as $row)
  {
    $topics[] = array('id' => $row['id'], 'topic' => $row['topic']);
  }

And the subtopics array like this,

<?php
  include $_SERVER['DOCUMENT_ROOT'] . '/artgibney/includes/db.inc.php';
  
  // Build the list of subtopics rows
  try
  {
    $result = $pdo->query('SELECT id, subtopic, topicid FROM subtopics');
  }
  catch (PDOException $e)
  {
    $error = 'Error fetching list of subtopics.';
    include 'error.html.php';
    echo $e;
    exit();
  }

  foreach ($result as $row)
  {
    $subtopics[] = array('id' => $row['id'], 'subtopic' => $row['subtopic'], 'topicid' => $row['topicid']);
  }

The actually forms themselves currently look like this,

<td>
                <select name="topic" id="topic">
                     <?php foreach($topics as $topical):
                           $value = $topical['topic'];
                           $selected = ($topic == $value) ? 'selected' : '';
                           echo "<option value='$value' $selected>$value</option>";
                      endforeach; ?>
                </select>
      </td>
            <td>
                <select name="subtopic" id="subtopic">
                     <?php foreach($subtopics as $subtopical):
                           $value = $subtopical['subtopic'];
                           $selected = ($subtopic == $value) ? 'selected' : '';
                           echo "<option value='$value' $selected>$value</option>";
                      endforeach; ?>
                </select>
      </td>

So when the topic ‘Mechanics’ is chosen only ‘Momentum’ should show in the subtopic menu.
Another issue with this is that this form is used for both inputting new data and for editing previous data.
I am trying to keep it that way.
Any help would be greatly appreciated.
Thanks,
Shane

Your not working with an array for starters. You’re working with an object. This syntax

allows for an arbritrary key to be sent, like this

mitems[key] 

Because the computer wouldn’t check the variable “key” if it had seen this

mitems.key

Arrays in JavaScript are numerically keyed only. Also, I don’t think you’re supposed to have numbers in your key names. That you do is a sign that you’re approaching things the wrong way. Much better would be

mitems.topic = [
   [ 'subtopic1', 'subtopic2'], 
  ['subtopic3', 'subtopic4']
];

This gives us an array of arrays. So topic 1’s subtopics are reached with mitems.topic[0] and subtopic 1 would be reached with mitems.topic[0][0];

2 Likes

There is surprisingly a really good wiki article that covers how Associate Arrays, Maps, and Dicts are implemented across languages.

And if you look at the menu on the right, there is actually a pretty big list of comparisons of things across languages that may help you in the future. Such as common Datatypes and Datastructures.

I actually just found these not too long ago and find it to be a pretty useful way to jumpstart language transitioning. Obviously, you need to learn more than what’s on wiki about each aspect but it’s a good way to get started and find what to look for. Which for me is the, knowing what to look for is the hardest part.

Hi,
Thanks for your reply. I thought it was an array because of this line.

I know almost nothing about JavaScript, need to at least do a few tutorials.

Thanks for this link, very useful.

Yes this is very interesting. Some really obscure languages too. I particularly like the ‘hello world’ comparison across languages.

I completely agree.
Thank you both for your help. A lot more learning needs to be done by me, before I can tackle this problem.
Shane

1 Like

Is it correct to say that here the array called mitems is an array of arrays. So ‘A’ is an array with values 1, 2, 3, etc. and ‘B’ is also an array of values a, b

        var mitems=new Array();
        mitems['A']=['1','2','3','4','5'];
        mitems['B']=['a','b'];
        mitems['C']=['i','ii','iii','iv'];
        mitems['D']=['(a)','(b)','(c)','(d)'];
        mitems['E']=['(i)','(ii)','(iii)','(iv)'];

So mitems[0] = A and A[2] = 3 or mitems[0][2] = 3 and so on.

My two arrays look like this, where the first one id $topics

Array
(
    [0] => Array
        (
            [id] => 40
            [topic] => Mechanics
        )

    [1] => Array
        (
            [id] => 41
            [topic] => Waves
        )

    [2] => Array
        (
            [id] => 42
            [topic] => Electromagnetism
        )

    [3] => Array
        (
            [id] => 43
            [topic] => Thermodynamics
        )
)

and the second $subtopics

Array
(
    [0] => Array
        (
            [id] => 45
            [subtopic] => Electromagnetic induction
            [topicid] => 42
        )

    [1] => Array
        (
            [id] => 44
            [subtopic] => Magnetism
            [topicid] => 42
        )

    [2] => Array
        (
            [id] => 43
            [subtopic] => Electricity
            [topicid] => 42
        )

    [3] => Array
        (
            [id] => 41
            [subtopic] => Diffraction
            [topicid] => 41
        )

    [4] => Array
        (
            [id] => 42
            [subtopic] => Interference
            [topicid] => 41
        )

    [5] => Array
        (
            [id] => 46
            [subtopic] => Momentum
            [topicid] => 40
        )

    [6] => Array
        (
            [id] => 47
            [subtopic] => engines
            [topicid] => 43
        )

)

If I could some how get the PHP arrays into the JS array, this could work!!!

What I would need to do is loop through $topics and take the value for $topics[‘topic’] and set it to be the ‘A’ in items[‘A’]. Then the first array in items would be items[‘Mechanics’]. Next this would be set equal to the value of $subtopics[‘subtopic’] where $topics[‘id’]==$subtopics[‘topicid’] and this comparison would be checked for each row of $subtopics. So that now we would have item[‘Mechanics’]=[‘momentum’].

So eventually the JS array would look like this,

mitems['Mechanics']=['Momentum'];
mitems['Waves']=['Diffraction','Interference'];
mitems['Electromagnetism']=['Electromagnetic induction','Magnetism','Electricity'];
mitems['Thermodynamics']=['engine'];

Two nested foreach loops in PHP would do this. But how would I set an array value in PHP equal to an array name in JS?
Can JS be inside PHP, the same way I can put PHP inside HTML?

Thanks,
Shane

You’re still stuck on Arrays. Drop that concept. You’re using JavaScript Objects now. The PHP Concept of an Array is (mostly) unique to PHP, in the sense that they are not represented the same way in other languages… They use Associative Arrays for everything.

Conversely, the concept of Objects in JavaScript are (mostly) unique to JavaScript in the sense that Objects in other languages are very different. JavaScript uses these Objects for everything.

In both cases, don’t get attached to the names. Because both cases have chosen the name of these datastructures poorly. Think of how it’s being represented.

This is not the job of an Array. Arrays are for sequential data, such as 1, 2, 3, 4, 5 or a, b. They are not for storing generic data, such as a list of sequences.

So, taking your example this is the right way to do it:

var mitems = {}; // Initialize the Object
mitems.A = ['1','2','3','4','5'];
mitems.B = ['a','b'];
mitems.C = ['i','ii','iii','iv'];
mitems.D = ['(a)','(b)','(c)','(d)'];
mitems.E = ['(i)','(ii)','(iii)','(iv)'];

Demo here: http://jsfiddle.net/dr5o8n8e/

Note: You need to view the result in your browser’s console. Here’s how you do that if you don’t already know how. I could have printed out the result, but if you’re using Firefox or Chrome then the result will be shown in the way an JSON Object should be shown.

Here is that data structure:

var topic = {
   id: 40,
   topic: 'Mechanics'
}; 

And subTopic

var subTopic = {
   id: 45,
   subtopic: 'Electromagnetic induction',
   topicid: 42
};

You could then access them like this:

alert(topic.topic);

or

alert(subTopic.subtopic);

Note: I would rename the actual name of the topic to “name” just for clarity, so I could print out topic.name instead of topic.topic, but that’s just me. Name it what you want.

But what you’re wanting is a list of these topics and subtopics, right? So then you need a generic structure to put them in.

function setTopic(topicId, topicName) {
    return { 
       id: topicId, 
       topic: topicName 
    };
}

function setSubTopic(subId, subName, topicId) {
   return { 
       id: subId, 
       subtopic: subName,
       topicid: topicId
    };
}

Then you can add them to an array of topics and sub topics like this:

var topics = new Array();
topics.push(setTopic(1, "Stuff 'n Junk"));

var subTopics = new Array();
subTopics.push(setSubTopic(42, "Soooo much stuff", 1));

Here’s a jsfiddle of that: http://jsfiddle.net/zvu17o09/3/
This one is viewable without the browser console.

Using an array here, because you probably do want to keep the sequence of the topics. Where as the order of id and topicName is completely irrelevant.

This is how the data is being represented in JSON:

[{1, "Stuff 'n Junk"}, {2, "Bonus for Demo"}]

and

[{42, "Soooo much stuff", 1}]

But now that I’ve said all that, from looking at what you’re trying to do… you might be better off actually storing the subTopics array of individual subTopic (singular object name) into the actual topics array.

That datastructure would look like this:

{
  id: 40
  topic: 'Mechanics'
  subTopics : [
     {
         id: 46,
         subtopic: 'Momentum' 
     },
     {
         id: 75
         subtopic: 'Some other Mechanical Term'
      }
  ]
}

That way, everything is under the topic object. You could access the sub objects like this topic.subTopics[0].id and it would print 46.

I’m not going to go through how to create this, becuase the concepts are outlined above. Basically you still need your setSubTopic function and you need to create an array of those, then append those to the topic object.

var topics = new Array();
topics.push(setTopic(1, "Stuff 'n Junk"));

var subTopics = new Array();
subTopics.push(setSubTopic(42, "Soooo much stuff", 1));

topics[0].subTopics = subTopics; // Create and add the subTopics we declared above to the first element in the list. 

Obviously, you’re going to need more logic to make sure you’re adding it to the right element of the topics array. But you get the idea.


If the naming confuses you, I used plural for arrays and singluar for objects. ie: topic and topics. It might get a little confusing if you didn’t catch that. Sorry.

4 Likes

Let your PHP script return the data in JSON format.
In Java script, create an “onchange” event handler for the “select” element having the identifier “topic”. Your event handler should clear the selection having the identifier “subtopic” and populate it with the subtopics of the selected topic.

Fascinating answer, @mawburn. I’m still learning JS from a very basic level, but this walkthrough is really useful.

Kind of a trivial question, but these days I read advice to use var topics = []; instead of var topics = new Array(); (hopefully I got that right). Any thoughts on that? I guess it doesn’t matter much.

1 Like

Thanks!

There isn’t a big enough difference for me to know off the top of my head. :smiley: I had to look it up. (the first answer is kinda wrong)

Basically, it looks like new Array() just allows you to override it. I work in Java as my primary backend so new Array() is more natural. I don’t usually use [] though I guess I should.

1 Like

The best answer I’ve seen in regard to this comes from YUI’s article, JavaScript, We Hardly new Ya

Also, people commonly come to JavaScript bringing the baggage from other languages that they’ve learned. Some people think that English spoken with a French accent is quite delightful. That is not quite the case with JavaScript.

Attempts to apply Java paradigms to JavaScript will only confuse you and slow you down. Fortunately though there’s a good group of people here that can help.

4 Likes

Whoa that was an epic response!

2 Likes

It’s useful to hear that, because as a non-programmer, I find that a large proportion of books, articles etc. tend to explain JS concepts with reference to other programming languages, which leaves me out in the cold. It’s quite frustrating. It’s just like my high school experience of learning Applied Mathematics: the teacher often brushed over key concepts because he expected us to have learned them in the Physics class—everyone in the class except me having a background in that subject.

1 Like

Hi,

With these points in mind what is the best way to learn arrays and objects in JS?
I have looked at W3CSchool but it is not very indept.
Thanks,
Shane

Well, JS Objects are weird. You have JSON, which is usually meant as datastructures, and" Objects" which contain methods and classes just like normal Objects in other languages. But they are the same thing.

var something = {
    iAmaVariable: 1234,
    iAmaFunction: function(number) {
        return this.iAmaVariable.toString() + number.toString();
    }
};

alert(something.iAmaVariable);
alert(something.iAmaFunction(5));

That said, my favorite resources are MDN:

Documentation

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object

Tutorials
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Working_with_Objects
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Introduction_to_Object-Oriented_JavaScript

I find these to be the most comprehensive and to-the-point way to get learned. :smile:

Here is a free book that’s pretty good:
http://eloquentjavascript.net/ (Chapter 4)

When you get a good handle on that, this is also really great free book:
http://addyosmani.com/resources/essentialjsdesignpatterns/book/

I’ve also heard good things about the Novice to Ninja series:
http://www.sitepoint.com/store/leaern-javascript-novice-to-ninja/

You can also use json_encode to better see how you can represent your PHP Arrays in Javascript. Personally, I try to be language agnostic and don’t rely on things like that.

1 Like

Check out W3Fools. I avoid W3Schools like the plague.

:slight_smile:

2 Likes

These are fantastic resources.
Looking forward to getting stuck into them.
I think my current problem with need to take a back step until I get at least the basics of JS.
Thanks,
Shane

1 Like

IMHO, everyone should learn vanilla JS before diving into any library like jQuery or MooTools. It will help you better understand what is happening (if you don’t understand it in vanilla JS, you’re pretty much just shaking something until it works.)

Just my $0.03283 worth.

:slight_smile:

So what is the significance of 0.03283 instead of 10¢ or whatever? Or is it just a random number?
I did Google it but nothing obvious came up.

:lol: inflation

4 Likes

@Mittineague nailed it… my two cents worth, after inflation. :smile:

:slight_smile:

1 Like