views:

133

answers:

5

This wasn't the question I was going to ask but I have unexpectedly run aground with JavaScript arrays. I come from a PHP background and after looking at a few websites I am none the wiser.

I am trying to create a multi-dimensional array.

var photos = new Array;
var a = 0;
$("#photos img").each(function(i) {
    photos[a]["url"] = this.src;
    photos[a]["caption"] = this.alt;
    photos[a]["background"] = this.css('background-color');
    a++;
});

Error message: photos[a] is undefined. How do I do this? Thanks.

+7  A: 

JavaScript does not have multidimensional arrays, but arrays of arrays, which can be used in a similar way.

You may want to try the following:

var photos = [];
var a = 0;
$("#photos img").each(function(i) {
    photos[a] = [];
    photos[a]["url"] = this.src;
    photos[a]["caption"] = this.alt;
    photos[a]["background"] = this.css('background-color');
    a++;
});

Note that you could have used new Array() instead of [], but the latter is generally recommended. Also note that you were missing the parenthesis of new Array() in the first line.


UPDATE: Following from the comments below, in the above example there was no need to use arrays of arrays. An array of objects would have been more appropriate. The code is still valid because arrays are objects in this language, but the following would have been better:

photos[a] = {};
photos[a]["url"] = this.src;
photos[a]["caption"] = this.alt;
photos[a]["background"] = this.css('background-color');
Daniel Vassallo
An Array holds numeric keys, not strings.
Alsciende
@Alsciende: That code is valid. An array is an object in JavaScript, and objects and hashtables are the same thing in this language. Therefore `photos[0]["url"]` is assigning a `url` property to `photos[0]`.
Daniel Vassallo
It's valid, but it's not proper. There's no point using an Array in that case, it's just confusing for novice people.
Alsciende
It's better to use `photos[a] = {};`
Ionuț G. Stan
@Alsciende: You have a point. Let me clarify the answer.
Daniel Vassallo
Thanks. But I still prefer my answer :)
Alsciende
@Alsciende: +1ed your answer. Your implementation is definitely better. Mine was just an attempt to address the OP's misunderstanding of arrays and multidimensional arrays.
Daniel Vassallo
A: 

multi-dimensional arrays are in these structure:

var photos = new Array();
photos[0] = new Array();

use it as :

photos[0][0] = this.src;

more on JS array here.

Reigel
+1  A: 

Douglas Crockford, of JSLint, would have you create it this way ("Use the array literal notation []"):

var photos = [];

Now remember that you want to create multi-dimensional arrays, which means an array inside an array. This means you need to create the inner-arrays:

$("#photos img").each(function(i) {
  photos[a] = []
  //continue
GlenCrawford
+1  A: 
var photos = [];
var imgs = document.getElementById("photos").getElementsByTagName("img");
for(var i=0;i<imgs.length;i++){
    photos.push({
        src:imgs[i].src,
        alt:imgs[i].alt,
        background:imgs[i].style.backgroundColor
    });
}

That should give you something that is roughly equivalent to this in PHP (I made up pretend data):

Array(
    [0] => Array(
        "src" => "logo.png",
        "alt" => "My Logo!",
        "background" => "#ffffff"
    )
)

I hope this helps!

tau
+1 for coding in plain js when possible
Alsciende
thanks for making that more readable.
tau
+5  A: 

You're trying to assign something to photos[a]["url"], photos[a]["caption"], etc., but photos[a] doesn't exist yet. photos is an empty Array at first, so you have to set photos[a] to something first. Since you want to use string keys ("url", "caption", etc), this something should be a plain object (the javascript equivalent to php associave arrays) (or a Hash if your code base allows it). Then you can use a literal object construct to simplify your function, and Array#push to get rid of the unnecessary a:

var photos = [];
$("#photos img").each(function(img) {
    photos.push({
      url: img.src,
      caption: img.alt,
      background: img.style.backgroundColor
    });
});

Also, make sure that this is actually your img element. Some each implementations will set this to the global object in your case.

edit: ok, it looks like jQuery.each automatically sets this to the iterated element, but doesn't wrap it in jQuery-goodness, so you have to either wrap this in $() or use plain DOM (I used the latter in my example).

edit2: anyway, using this is kind of strange since the callback function passed to each receives an argument. Might as well use this argument (renamed).

Alsciende
The only problem with `this` is that it doesn't have a `css` method. It must first be wrapped inside a jQuery object.
Ionuț G. Stan
I don't much about jQuery. I'll use your advice.
Alsciende