views:

69

answers:

2

I have an javascript array, which looks like:

var styles = new Array();
styles[0] = { ... Position: 0, ... };
styles[1] = { ... Position: 1, ... };
styles[2] = { ... Position: 2, ... };
...
styles[N] = { ... Position: N, ... };

I use this array to display a list, where each item is a div. The end result is this:

<div id="container">
 <div>... item 1...</div> 
 <div>... item 2...</div> 
 <div>... item 3...</div> 
</div>

Now the "container" div is also jquery sortable. That way I can drag/drop the items and change the position. Now whenever the user drags an item to a different position I update the positions back in the array by looping through the div items, which is pretty bad. It looks more or less like that:

var items = $("#container");
for (var i = 0; i < items.length; i++)
{
    ....
    styles[i] = { ... Position: i, ... };
}

Is there a better way to achieve this?

Update 1:

I need to save the positions in the database, which is why I need change my array after the list has been changed. The list changes depending on other criterias. So I could have a list of 10 items or I could have a list of X items. It depends on which list the users selects. Now if the user changes one list and then wants to see a second list, then I need to make sure that the first list maintains the positions.

A: 

Why is it you need to know the position?

You won't have to track the position at all if you can rely on jQuery's $.index() method.

When you need to know the position of an element, just use something like the following...

$("#container div").index(myDiv);

UPDATE 1:

I see -- the server needs to know the positions to store them in the DB. Nevertheless, I'm not crazy about the notion of having 2 representations of this data on the page: markup (divs), and JS array. I would look at changing my code to build the array (from the divs) at the last second... just before you send it to the server. That way you can loop over the divs in order and you won't have to maintain the order in parallel in a separate data structure. Keeping 2 structures in sync in messy and can be error-prone

Little disclaimer: I don't know everything about your page. I don't know anything about your situation that would make this suggestion unworkable, but I suppose there may be something out there.

Little tip: if there are data elements int he area that aren't represented in the markup somehow, consider just tagging the markup with arbitrary info.

<a href="whatever.html" foo="bar">link text</a>
Drew Wills
I updated my question. Please see my comment.
vikasde
+1  A: 

I think Drew Wills response is on the mark, and this might also help. A div is a JavaScript object, which means you can add properties to it. So you might be able to reduce the number of lines of JavaScript code and increase the code's expressiveness by sticking your "information object" right onto each div, meaning you'd no longer need your array.

Where does your array come from in the first place? I'm going to assume it is a JSON-ified version of some data you have on the server. So I'm assuming (guessing) that you have some kind of "each" or for loop that creates the divs from the array, perhaps like this:

for (var i = 0; i < styles.length; i++)
{
    var newDiv = $("<div>" + style[i].item + "</div>";
    $("#container").append(newDiv);
}

Assuming you have that, then you could modify it to this:

for (var i = 0; i < styles.length; i++)
{
    var newDiv = $("<div>" + style[i].item + "</div>";

    // KEY NEW LINE FOLLOWS:
    newDiv.myCustomObject = styles[i];

    $("#container").append(newDiv);
}

Now, as the divs get sorted all over the place, this "myCustomObject" goes along with them. You don't need the array anymore. If you need the "Position" property on "myCustomObject" to be updated, use the "index" property of the div, as Drew Wills said.

So, imagine that your "styles" object has a property in it called "Color". Imagine you want to show an alert on click that tells the color associated with the div they clicked on. You can now accomplish this without needing the "styles" array, because the divs now have everything you need. So you could do this:

$("#container div").click(function() {
   alert("The color is " + this.myCustomObject.Color);
});

Later, when it comes time to post or send via ajax the positions, you could do this:

$("#container div").each(function(index) {
   this.myCustomObject.Position = index;
}

NOTE: Also, some people would prefer to use the JQuery data() method to associate "myCustomObject" with the div. It achieves the same result and perhaps gets garbage collected more completely in some browsers.

Charlie Flowers
Sorry, but I dont really understand it. Do you have an example that would show it?
vikasde
I added an example ... hopefully even if my guesses about the rest of your app are not exactly on the mark, you can still see what I'm getting at.
Charlie Flowers
thanks for the example. But how will the position update when i sort the divs? I dont see the logic here. If I have 10 items and I drag the 9 item to the 2nd place, then all other indexes after 1 need to changed. Does that make sense?
vikasde
I added an example of that to my response.
Charlie Flowers
I see what you mean. Thanks for the tip. I will try it out.
vikasde