views:

929

answers:

4

I have an associative array (object) of the following construction

var menu = new Object('Submenu A','Submenu B','Submenu C','Submenu D');
menu['Submenu A']=new Object();
menu['Submenu A']['Option A']= 'foo blah text';
menu['Submenu A']['Option B']= 'blah more text';
menu['Submenu B']['Option A']= 'blah blah';
menu['Submenu B']['Option B']= 'texty text';
...
etc.

This is iterated over a for..in loop which breaks when using prototype due to extending the class with methods like toJSON() and camelise()

I've attempted using Prototype's .each method however it errors out reporting that menu['Submenu A'] is undefined, it can't seem to locate the options that are defined under it.

What is the proper way to iterate over an associative array in prototype?

Further clarification (thanks for the answers so far). I'm slowly migrating a project over to using prototype, but it has large amounts of code that aren't prototype compatible yet. The code in question is in a library used by several other files. The code as is called by a function, initialize_menu and contains the code

for (var i=0; i < menu.length; i++) {
    populate_sub_menu(menu[i])
}

The submenu function is structured like this

function populate_sub_menu(subMenu){
    for (var option in menu[subMenu]) {
        html+=menu[subMenu][option]+'html'+subMenu+option;
    }
}

I'm leaving out code regarding getting html elements and such that aren't related to the problem.

+1  A: 

You want Prototype's Hash.

Abie
A: 

You could simply check that if the current object is of the type you are looking for (or one you are trying to avoid, like function).

geowa4
+1  A: 

Use the hasOwnProperty method, which will only return true for properties you have defined on the object instance:

  for (var option in menu[subMenu]){
    if(menu[subMenu].hasOwnProperty(option)){
      html+=menu[subMenu][option]+'html'+subMenu+option;
    }
  }
Zach
+5  A: 

To create a new object with no properties, use:

var menu = new Object();

The Object constructor actually takes one optional argument. Now let's look at what you have:

var menu = new Object('Submenu A','Submenu B','Submenu C','Submenu D');

Only the first argument ('Submenu A') is being used while the others are simply ignored. However, passing a string literal to the Object constructor causes a new String object being returned instead of an Object object. I'm speculating that, that may be reason Prototype's each() is acting up (if it's really failing because of this).

You mentioned that "it errors out reporting that menu['SubmenuA'] is undefined". Does your question have a typo? You're setting the "Submenu A" property, with a space before the "A", while the error you reported seems to lack the space.

You also seem to be taking the long route in setting the object properties. Using the object literal syntax will be a lot shorter and less error-prone:

var menu = {
    "Submenu A": {
        "Option A": "foo blah text",
        "Option B": "blah more text"
    },
    "Submenu B": {
        "Option A": "blah blah",
        "Option B": "texty text"
    }
};
Ates Goral
Thanks, I rewrote the object the way you suggested, and now it's working in both the Prototype.js and non Prototype pages in my project.
borkencode