Dynamically created DropDownList values as Key for Javascript array
<p>I'm using ASP.NET to send REST requests to a server I have no control of. One type of request is for a specific product. The product may be available in many different variations. Some of the variations could be Size, Color, Metal (gold, silver, etc). In the case of some products there could be a Year variation and a Make (Ford, Dodge, etc.). The point here is that the variations are many and sometimes there is only a single variation, while other times there may be 3 or 4 variations for a product.</p>

<p>Also, there are not set lists of how many selections a variation might contain. For example, one product may be available in Pink, Green, Blue of a Color variation, while another product might only be available in Black or White. Size could sometimes contain 8, 10, 12 and 14 for a jewelry item, or Small, Medium, Large for a clothing item.</p>

<p>The combination of variations for a product are always returned in the REST response. For example, I'll always know a products variation attributes like 'Color', 'Size', etc. I've found that the cleanest way of presenting these variation options is by using DropDownLists. I can dynamically create a DropDownList of 'Color' and populate it with options of Pink, Green and Red - or whatever.</p>

<p>A product with a Color of Pink and a Size of Small has a different product ID than one which is Pink and Large.</p>

<p>So, if a web visitor looks up a product and then selects the desired variations, I need client side script logic that will associate a product ID (based on the variations selected) so the product can be added to his shopping cart.</p>

<p>The REST response contains an array of product IDs that are associated with the combinations of variations.</p>

<p>I'm sorry for such a lengthy explanation, but I don't have any code to present at this point. </p>

<p>What I'm wanting to know is, since JavaScript doesn't support multidimensional arrays, what options do I have to use client-side Javascript logic to determine a product ID based on the selected values of one or more DropDownLists?</p>

<p>One the server side, either in my XSLT templates or in the ASP.NET codebehind, I can use "Page.ClientScript.RegisterArrayDeclaration" in some fashion, but I really need some logic that's ignorant to what the specific variation names are.</p>

<p>So, for example, I have a product called "WIDGET" and it has the following variations (layed out as ProductID, variation1, variation2):</p>

<pre><code>"00001", "Black", "Small"
"00002", "Pink", "Small"
"00003", "Red", "Small"
"00004", "Black", "Medium"
"00005", "Pink", "Medium"
"00006", "Red", "Medium"
"00007", "Black", "Large"
"00008", "Pink", "Large"
"00009", "Red", "Large"
</code></pre>

<p>And I have 2 DropDownLists:</p>

<p>Color: Black, Pink, Red</p>

<p>and </p>

<p>Size: Small, Medium, Large</p>

<p>How would I determine the ProductID based on the selected Values of variation1 and variation2? Keep in mind these attributes are dynamically created/populated. The client Javascript needs to be generic. I probably need to create several arrays for the Javascript logic.</p>

<p>One to pass the possible variations:</p>

<pre><code>Page.ClientScript.RegisterArrayDeclaration("product_variation", "Color")
Page.ClientScript.RegisterArrayDeclaration("product_variation", "Size")
</code></pre>

<p>Another, as above, to contain the ProductIDs and their associated variations:</p>

<pre><code>Page.ClientScript.RegisterArrayDeclaration("product_1_ID", "00001")
Page.ClientScript.RegisterArrayDeclaration("product_1_Color", "Black")
Page.ClientScript.RegisterArrayDeclaration("product_1_Size", "Small")

Page.ClientScript.RegisterArrayDeclaration("product_2_ID", "00002")
Page.ClientScript.RegisterArrayDeclaration("product_2_Color", "Black")
Page.ClientScript.RegisterArrayDeclaration("product_2_Size", "Medium")
</code></pre>

<p>etc. etc. But to be honest, I do not know Javascript and I just don't know how to pull this off without seeing an example. I've searched, but haven't been able to find anything close. I could also create some hidden inputs in the asp page if it would help with the client side script.</p>

<p>Can anyone point me to an example that will help me with a solution to this? Is there an easier/more suitable way of doing what I need?</p>

<p>Thank you for reading all of this. I almost didnt post it since it's so lengthy...</p>

<p><strong>EDIT:</strong></p>

<p>The ideas submitted by gilly3 below are right on with how I thought this should work. Again, I have very limited experience with Javascript of any flavor, but I've followed the instructions as best as I can. Am having a problem someplace though, so I wanted to display my progress and ask if you see what's wrong.</p>

<p>In Product.aspx I create a hidden field containing the variations of the product being viewed:</p>

<pre><code>&lt;input id="hfdatalist" type="hidden" value="[
{"Id": "00001","Color": "Tidal", "Size": "2"},
{"Id": "00002","Color": "Tidal", "Size": "4"},
{"Id": "00003","Color": "Tidal", "Size": "6"}, 
{"Id": "00004","Color": "Tidal", "Size": "8"}, 
{"Id": "00005","Color": "Tidal", "Size": "10"}, 
{"Id": "00006","Color": "Tidal", "Size": "12"}, 
{"Id": "00007","Color": "Tidal", "Size": "14"}, 
{"Id": "00008","Color": "Tidal", "Size": "16"}
]" /&gt;
</code></pre>

<p>And a hidden field containing the variation attributes (Color and Size):</p>

<pre><code>&lt;input id="hfpropctlmap" type="hidden" value=
"{"ddSize": "Size", "ddColor": "Color"}"
/&gt;
</code></pre>

<p>I have two dropdownlists. One for Size with an id of ddSize and another for Color with an id of ddColor. ddColor (in this case) has only one option, "Tidal". ddSize has multiple options, 2, 4, 6, 8, 10, 12, 14 and 16. Clicking any option in either of these dropdowns will fire the following Javascript.</p>

<p>In Product.aspx I include the Javascript example as provided by gilly3. I made some assumptions about where to put some of the code, but for the most part I've used it verbatim:</p>

<pre><code>&lt;!-- Augment JS files --&gt;
&lt;script type="text/JavaScript" src="../Scripts/augment.min.js"&gt;&lt;/script&gt;

&lt;!-- Variations Support Script --&gt;
&lt;script type="text/JavaScript"&gt;
    $("select").change(function () {

        var data = $.parseJSON($("#[id*='hfdatalist']").val());
        var propertyControlMap = $.parseJSON($("#[id*='hfpropctlmap']").val());
        var filteredData = data;

        var selections = $("select").map(function () {
            return {
                Property: propertyControlMap[this.id],
                Value: $(this).val()
            };
        }).get();

        filteredData = data.filter(function (item) {
            return selections.every(function (selection) {
                return item[selection.Property] == selection.Value;
            });
        });
        var selectedId = filteredData.length == 1 ? filteredData[0].Id : "";
        $("#[id*='SelectedVariationASIN']").val(selectedId)
    }); 
&lt;/script&gt;
</code></pre>

<p>I realize this code is a little messy since I have some debugging assistance included. There are 2 alerts that display the contents of the hidden fields saved to variables test and test1. Both of these display the value of the hidden fields perfectly (I think!).</p>

<p>I set a breakpoint and view the contents of the data variable. There are 8 elements to the array (0-7) and each one of them contains correct Id, Color and Size values. The property names appear correctly and the actual data is valid.</p>

<p>Same with propertyControlMap. When I view its data, the Property names and values are correct. There are 2 elements (0-1).</p>

<p>Of course, filteredData is also correct since its just a copy of the data var at this point.</p>

<p>The next var I look at is selections. Here is the first sign that something isn't quite right. After selections is assigned and I view its value, I can see there are 9 methods and 2 elements (0-1). Upon looking at the elements, selections[0].Property is 'undefined' and its value is incorrect '1036682'. I recognize the value from the value stored in another hidden field on the page called "hfSearchIndex". I have no clue why this happens. This field isn't referenced in the script at all. It has nothing to do with this part of my program logic.</p>

<p>Odd though, selections[1].Property also contains 'undefined', though Value contains the actual value of whatever Size I clicked on in the ddSize dropdownlist. So, it's partially correct.</p>

<p>From this point, the code is unpredictable and probably not worth commenting on, except to say that the last line of code, selectedId, returns ''.</p>

<p>gilly3 or anyone else, can you see what I've done wrong?</p>

<p><strong>EDIT #2</strong></p>

<p>gilly3 mentioned that the propertyControlMap might not contain the correct IDs of the dropdownlist controls. I'm not positive, but I think it does contain the correct IDs. However, there is a Master Page involved and also an asp:PlaceHolder control. So the Name attribute does have some mangling going on.</p>

<p>Here are some facts:</p>

<ol>
<li>hfdatalist looks perfect (as displayed above).</li>
<li>hfpropctlmap looks perfect (as displayed above).</li>
<li>var data gets initialized correctly. Each element of the array contains perfect ID, Color and Size values as specified in the hfdatalist hidden field. (ie: 00001, Black, Small).</li>
<li>var propertyControlMap gets initialized correctly. Each element of the array contains perfect ID of dropdownlists and the correct variation name. (ie: ddColor and Color).</li>
<li>The first indication of a problem is at <code>var selections =</code> in the Javascript. After this line of code is executed, <code>selections</code> doesn't contain valid data. Instead of selections equal to: ID=00001, Color=Black, Size=Small it equals undefined=1036682, Color=Black, Size=Small. For some reason, the ProductID isn't getting set correctly.</li>
</ol>

<p>After the page is rendered, I view the source and here are the dropdownlists:</p>

<pre><code>&lt;select name="ctl00$PageContent$ddSize" id="ddSize"&gt;
    &lt;option value="Small"&gt;Small&lt;/option&gt;
    &lt;option value="Medium"&gt;Medium&lt;/option&gt;
&lt;/select&gt;

&lt;select name="ctl00$PageContent$ddColor" id="ddColor"&gt;
    &lt;option value="Black"&gt;Black&lt;/option&gt;
    &lt;option value="Cobalt"&gt;Cobalt&lt;/option&gt;
    &lt;option value="Coral"&gt;Coral&lt;/option&gt;
    &lt;option value="Jade"&gt;Jade&lt;/option&gt;
    &lt;option value="Yellow"&gt;Yellow&lt;/option&gt;
&lt;/select&gt;
</code></pre>

<p>Further down the page, there is another hidden field that has absolutely nothing to do with the logic being discussed in this question/answer:</p>

<pre><code>&lt;input type="hidden" name="SearchIndex" value="1036682"&gt;
</code></pre>

<p>I can't figure out why the value of this field ("1036682") is being used in the ProductID value of <code>var selections</code></p>

<p>I'm not sure how to document my problem any further. I do suspect, like gilly3, that there is something incorrect about the way I'm referring to control IDs, though propertyControlMap does contain completely valid/correct data in all of its elements/properties.</p>

<p>If this is a problem with control IDs due to a Master Page and PlaceHolder, how do I get around this? </p>

<p>NOTE: The dropdownlist controls are created in an XSLT Transform using XSLT Stylesheets ran on the REST response received. The hidden fields are created in the page codebehind using a deserialized REST response.</p>

<p>Thank you for helping me on this gilly3. I'm really stuck due to my lack of knowing Javascript. I have to use Javascript to be cross-browser compatible in this situation. Makes me a bit nervous to include code in my project that I really don't know much about, but I will pay special attention to it.</p>

<p>Hope I'm not being confusing. :S</p>
