2

Let's say I have:

var directions = [ "name", "start_address", "end_address", "order_date" ];

I'm trying to find a slick, fast way to turn that array into this:


data: {
  "directions[name]"          : directions_name.val(),
  "directions[start_address]" : directions_start_address.val(),
  "directions[end_address]"   : directions_end_address.val(),
  "directions[order_date]"    : directions_order_date.val()
}

Notice the pattern. The name of the array "directions" is the prefix to the values. I'm interested how people can either do this or at least suggest a way for me to try.

Any tips would be appreciated.

Thanks!

EDIT **

Thanks for the suggestions so far. However, I forgot to mention that the array "directions" needs to be dynamic.

For example, I could use:

places = ["name", "location"]

should return

data: {
  "places[name]"     :  places_name.val(),
  "places[location]" :  places_location.val()
}
alpha = ["blue", "orange"]

should return

data: {
  "alpha[blue]"   : alpha_blue.val(),
  "alpha[orange]" : alpha_orange.val()
}

So basically I could just pass an array into a function and it return that data object.

 var directions = ["name", "start_address", .... ];
 var data = someCoolFunction( directions );

Hope that makes sense.

** EDIT **************

I want to thank everyone for their help. I ended up going a different route. After thinking about it, I decided to put some meta information in the HTML form itself. And, I stick to a naming convention. So that an HTML form has the information it needs (WITHOUT being bloated) to tell jQuery where to POST the information. This is what I ended up doing (for those interested):

    // addBox
    // generic new object box.
    function addBox(name, options) {
        var self = this;
        var title = "Add " + name.charAt(0).toUpperCase() + name.slice(1);
        var url = name.match(/s$/) ? name.toLowerCase() : name.toLowerCase() + "s";
        allFields.val(""); tips.text("");

        $("#dialog-form-" + name).dialog( $.extend(default_dialog_options, {
            title: title,
            buttons: [
                {   // Add Button
                    text: title,
                    click: function(){
                        var bValid = true;
                        allFields.removeClass( "ui-state-error" );

                        var data = {};
                        $("#dialog-form-" + name + " input[type=text]").each(function() {   // each is fine for small loops :-)
                            var stripped_name = this["name"].replace(name + "_", "");
                            data[name + "[" + stripped_name + "]"] = $("#dialog-form-" + name + " #" + name + "_" + stripped_name).val();
                        });

                        // verify required fields are set
                        $("#dialog-form-" + name + " input[type=text].required").each(function() {
                            bValid = bValid && checkLength( $(this), $(this).attr("name").replace("_", " "), 3, 64 );
                        });

                        // find sliders
                        $("#dialog-form-" + name + " .slider").each( function() {
                            data[name + "[" + $(this).attr("data-name") + "]"] = $(this).slider( "option", "value" );
                        });

                        data["trip_id"] = trip_id;
                        if(options != null) {   $.extend(data, options); } // add optional key/values
                        if(bValid) {
                            $(".ui-button").attr("disabled", true);
                            $.ajax( { url : "/" + url, type : "POST", data : data } );
                        }
                    }
                },
                { text: "Cancel", click: function(){$( this ).dialog( "close" );} }
            ]
        }));
    }
cbmeeks
  • 11,248
  • 22
  • 85
  • 136
  • 3
    I'm not sure I know what you're trying to do.. – xj9 Dec 01 '10 at 03:31
  • Why not use direction instead of data? like this var direction = { name: name.val(), ...} – user347594 Dec 01 '10 at 03:45
  • Looks like writing a function that can access the name of a passed variable is not trivial: http://stackoverflow.com/questions/1009911/javascript-get-argument-value-and-name-of-passed-variable – Andrew Whitaker Dec 01 '10 at 03:54
  • @Andrew Whitaker Yes, it isn't trivial. But you can get around this by not passing a value, but simply passing the string in the first place (see my solution). – mgiuca Dec 01 '10 at 04:03

2 Answers2

4

It's really unclear what you want here. Perhaps you should give the interface to the function you want, and an example of some code which sets up some sample variables and calls the function.

What you seem to be asking for is to dynamically find variables which you have already declared in the environment, such as directions_name and directions_start_address, and call the val() method on each of them, then construct a dictionary mapping strings to those results. But the keys of the dictionary contain JavaScript syntax. Are you sure that's what you want?

function transform(name)
{
    var data = {};
    var names = window[name];
    for (var i=0; i<names.length; i++)
    {
        data[name + "[" + names[i] + "]"] = window[name + "_" + names[i]].val();
    }
    return data;
}

Edit: To use JQuery to look up objects by ID instead of the above approach (which looks up global variables by name):

function transform(name)
{
    var data = {};
    var names = $("#" + name);
    for (var i=0; i<names.length; i++)
    {
        data[name + "[" + names[i] + "]"] = $("#" + name + "_" + names[i]).val();
    }
    return data;
}

This will look up the name in the global space of the window (which will work in a browser anyway). You call that function with "directions" as the argument. For example:

var directions = [ "name", "start_address", "end_address", "order_date" ];
var directions_name = {"val": function() {return "Joe";}};
var directions_start_address = {"val": function() {return "14 X Street";}};
var directions_end_address = {"val": function() {return "12 Y Street";}};
var directions_order_date = {"val": function() {return "1/2/3";}};
data = transform("directions");

Is that what you want?

(Note: I see someone else posted a solution using $ and "#" ... I think that's JQuery syntax, right? This works without JQuery.)

Edit: Note that this lets you use a dynamic value for "directions". But I'm still not sure why you want those keys to be "directions[name]", "directions[start_address]", instead of "name", "start_address", etc. Much easier to look up.

Edit: I fixed my sample code to use functions in the values. Is this really what you want? It would be easier if you weren't calling val() with parens.

mgiuca
  • 20,958
  • 7
  • 54
  • 70
  • Thanks for your input. Yeah, it's pretty complex. Here is what I'm trying to do. Basically, I use JQuery UI to build some forms. Then these forms call .AJAX and POST data to a server. I have the same code over and over again for many forms. The only real difference is the FIELDS they access. Form A is directions. Form B is maps, etc. I want to dynamically build those AJAX data options so that I can have ONE function to dynamically build forms. Does that make more sense? I can post more code if needed. – cbmeeks Dec 01 '10 at 03:49
  • I see. So you are calling `val()` because the variables `directions_name`, for example, are objects where the `val()` method looks up their data. Then you might want to replace the 'window' thing with `$("#...")` as SLaks suggested. That should look up these things by ID. Use my solution but replace `window[name]` with `$("#" + name)`. It also explains why you are putting the name "directions" into the output dictionary; but you might consider using an underscore instead of square brackets. – mgiuca Dec 01 '10 at 03:56
  • Thanks again. I will give that a shot. The brackets are because I am POSTing to a rails app. – cbmeeks Dec 01 '10 at 04:01
  • I see. I haven't used Rails, but I assume it has some automatic way to convert a series of POST variables named `"a[x]"`, `"a[y]"`, `"a[z]"` into a dictionary `a = {"x": ..., "y": ..., "z": ...}` ? – mgiuca Dec 01 '10 at 04:04
  • That's right. It will take "directions[name]" and update the directions model (name) property. – cbmeeks Dec 01 '10 at 04:19
1

Like this:

var data = { };
for(var i = 0; i < directions.length; i++) {
    var name = directions[i];
    data["directions[" + name + "]"] = $('#directions_' + name).val();
}

Or,

    data["directions[" + name + "]"] = directionsElements[name].val();

EDIT: You can pass an array and a prefix.

SLaks
  • 868,454
  • 176
  • 1,908
  • 1,964