2

I'm trying to implement chained ajax selects from this jQuery plugin: http://www.appelsiini.net/projects/chained

I'm using the remote method.

I have a problem where my select boxes show the "default" (blank) value last in the select as seen here:

This is a problem because I have 5 chains, so when the blank value isn't selected by default, it does 5 sequential lookups. It also isn't working like it shows on the demo page where the default value is selected by default instead of a real value.

A JSON request from my server returns this:

{"":"","1":"Test #1","2":"Test #2"}

So as you can see, it's not the order that my JSON is returning.

This is my HTML:

<label class="control-label" for="branch">Branch</label>
<select id="branch" name="branch">
    <option value=""></option>
    <option value="1">Foo</option>
    <option value="2">Bar</option>
</select>
<label class="control-label" for="facility">Facility</label>
<select id="facility" name="facility">
    <option value=""></option>
</select>

<script src="/js/chained.js"></script>
<script>
    $(document).ready(function() {
        $("#facility").remoteChained("#branch", "/src/record.json.php");
    } );
</script>

So now I'm lost and since I can't read/write JavaScript very well, I'm hoping someone can see the issue and help me out.

Jimmy Sawczuk
  • 13,488
  • 7
  • 46
  • 60
Ryan Mortier
  • 763
  • 1
  • 10
  • 23

2 Answers2

1

It happens because,

Chrome and probably Opera sort object properties automatically

So your JSON also is sorted in for loop.

var json = {"":"","1":"Test #1","2":"Test #2"};
for(var i in json)
   console.log(i);

/* Result : 1 2 (null) */

DEMO

Solution 1:

If you change your index as string that will not be sorted.

var json = {"":"","t1":"Test #1","t2":"Test #2"};
for(var i in json)
   console.log(i);

/* Result : (null) t1 t2 */

DEMO

Solution 2:

Changing plug-in

Here is the edited plugin code that works with array,

  /*
 * Remote Chained - jQuery AJAX(J) chained selects plugin
 *
 * Copyright (c) 2010-2011 Mika Tuupola
 *
 * Licensed under the MIT license:
 *   http://www.opensource.org/licenses/mit-license.php
 *
 */

(function($) {

    $.fn.remoteChained = function(parent_selector, url, options) { 

        return this.each(function() {

            /* Save this to self because this changes when scope changes. */            
            var self   = this;
            var backup = $(self).clone();

            /* Handles maximum two parents now. */
            $(parent_selector).each(function() {
                $(this).bind("change", function() {

                    /* Build data array from parents values. */
                    var data = {};
                    $(parent_selector).each(function() {
                        var id = $(this).attr("id");
                        var value = $(":selected", this).val();
                        data[id] = value;
                    });

                    $.getJSON(url, data, function(json) {
                        var selectedVal;
                        /* Clear the select. */
                        $("option", self).remove();

                        /* Add new options from json. */
                        for (var key in json.options) {
                            var k = json.options[key];
                            /* This sets the default selected. */
                            if ("selected" == k.name) {
                                selectedVal = k.value;
                                continue;
                            }
                            var option = $("<option />").val(k.value).append(k.name);
                            $(self).append(option);    
                        }

                        /* Loop option again to set selected. IE needed this... */ 
                        $(self).children().each(function() {
                            if ($(this).val() == selectedVal) {
                                $(this).attr("selected", "selected");
                            }
                        });

                        /* If we have only the default value disable select. */
                        if (1 == $("option", self).size() && $(self).val() === "") {
                            $(self).attr("disabled", "disabled");
                        } else {
                            $(self).removeAttr("disabled");
                        }

                        /* Force updating the children. */
                        $(self).trigger("change");

                    });
                });

                /* Force updating the children. */
                $(this).trigger("change");             

            });
        });
    };

    /* Alias for those who like to use more English like syntax. */
    $.fn.remoteChainedTo = $.fn.remoteChained;

})(jQuery);

To work with this updated plugin, you should use this JSON format,

{
    "options" : [
      { "value" : "", "name" : ""},
      { "value" : "1", "name" : "Test #1"},
      { "value" : "2", "name" : "Test #2"},
    ]
}

If you want to set a default selected item (for example "Test #1" is selected), so you can do that like this,

{
    "options" : [
      { "value" : "", "name" : ""},
      { "value" : "1", "name" : "Test #1"},
      { "value" : "2", "name" : "Test #2"},
      { "value" : "1", "name" : "selected"}
    ]
}

How can I use this edited plugin?

Just clear all the code in /js/chained.js than paste the new one.

Community
  • 1
  • 1
Okan Kocyigit
  • 13,203
  • 18
  • 70
  • 129
  • Hmm, you seem to be correct. Is there a value I can assign to my "default" value that is sorted before the number 1? I don't really want to prefix my values with a letter because then I have to use a string function to remove it when I do a database call. – Ryan Mortier Aug 08 '12 at 00:23
  • Or, is there a javascript/jquery function I can use to sort my values by key? – Ryan Mortier Aug 08 '12 at 00:29
  • @morrty, no, if you want to stand on this way, you should send an array in json, so that will not be iterated in sort of index. But of course you must edit the plug-in also. – Okan Kocyigit Aug 08 '12 at 14:03
  • Editing the plugin is the part I don't know how to do, unfortunately. – Ryan Mortier Aug 08 '12 at 18:47
  • @morrty, I have edited it for you, check my updated answer again. – Okan Kocyigit Aug 08 '12 at 22:18
  • Wow, thank you very much, I definitely didn't expect you to do this but I appreciate it. – Ryan Mortier Aug 09 '12 at 12:54
0

It looks like the JSON returned from the server is wrong.

It should contain a selected field like this:

{"":"--","3-doors":"3 doors","5-doors":"5 doors","coupe":"Coupe","cabrio":"Cabrio","selected":"coupe"}

That is taken from the examples here:

http://www.appelsiini.net/projects/chained

In your case the server should return:

{"":"","1":"Test #1","2":"Test #2","selected":""}
Dave L.
  • 9,595
  • 7
  • 43
  • 69
  • I gave that a try, it works as in the default value is selected, however, the default value is still last in the select box instead of first. – Ryan Mortier Aug 07 '12 at 23:39