views:

69

answers:

3

I have a page that has a series of "related" selects. Everything works fine UNLESS there is an option that is pre-selected. I can set the "pre-selection" to work if I put an "alert" in the code but without it it doesn't work.

For Example:

function loader(){
    if ($("#prod_1").val() > 0){
        switchBatch(1);
        $('#batch_1').val('15');
        updateMax(1);
    }
    if ($("#prod_2").val() > 0){
        switchBatch(2);
        alert('yup');
        $('#batch_2').val('35');
        updateMax(2);
    }
}
$(function() {
    loader();
});

The second one that has the "alert('yup');" in it works but the first one doesn't.

The "switchBatch()" is a function that loads the options (from an ajax call) into the batch select control. Both instances load the options but only the second one is then selecting the correct option.

Any suggestions?

Lance

Here is the whole thing:

<script>
    maxVals = [];
    function switchBatch(idNum){
        maxVals = [];
        $("#max_"+idNum).val('');
        $.ajax({
            type: "POST",
            url: "/cfc/product.cfc?method=pialJson",
            data: ({
                productID: $("#prod_"+idNum).val()
            }),
            dataType: "json",
            success: function(result){
                options = '';
                var colMap = new Object();
                for(var i = 0; i < result.COLUMNS.length; i++) {
                    colMap[result.COLUMNS[i]] = i;
                }
                for (var i = 0; i < result.DATA.length; i++){
                    options += '<option value="' + result.DATA[i][colMap["BATCHID"]] + '">' + result.DATA[i][colMap["BATCHNAME"]]+ '</option>';
                    maxVals[i] = result.DATA[i][colMap["INSTOCK"]];
                }
                $("select#batch_"+idNum).html(options);
                updateMax(idNum);
            }
        });
    }
    function updateMax(idNum){
        thisOne = $("#batch_"+idNum).attr("selectedIndex");
        $("#max_"+idNum).val(maxVals[thisOne]);
        checkMax(idNum);
    }
    function checkMax(idNum){
        $("#qty_"+idNum).removeClass('red');
        if ($("#qty_"+idNum).val() > $("#max_"+idNum).val()){
            $("#qty_"+idNum).addClass('red');
        }
    }

    function loader(){
        if ($("#prod_1").val() > 0){
            switchBatch(1);
            alert('yup');
            $('#batch_1').val('<cfoutput>#batch_1#</cfoutput>');
            updateMax(1);
        }
        if ($("#prod_2").val() > 0){
            switchBatch(2);
            alert('yup');
            $('#batch_2').val('<cfoutput>#batch_2#</cfoutput>');
            updateMax(2);
        }
    }
    $(function() {
        loader();
    });
</script>
A: 

Without the code of updateMax(), it's hard to say what's exactly going on.

One approach you can try is, attach updateMax() to the onchange listener of the select control (i.e. $('#selectID').change(updateMax)), and instead of calling updateMax(), do $('#selectID').change().

William
The updateMax() sets a readOnly text input with a value based on the batch select. I don't think that is the problem as the batch select isn't changing (unless the alert is present) It seems that the line that is not working correct is:$('#batch_2').val('35');
Lance
+1  A: 

I think the pre-selects aren't working because the "switchBatch()" function uses ajax. The JavaScript code after the call to "switchBatch()" is executed before the ajax call is complete, so the select elements are empty. But it works in the second if-block because of the alert(), which gives the ajax call enough time to complete and populate the select element.

Stian
That sounds VERY likely but I am not sure how to "pause" and wait for the ajax. Is there a way to say run the switchBack and wait until is is done and then do the updateMax()
Lance
That is what the ajax callback function is for, e.g. success. I suggest you to do some debug prints, i.e. console.log(...) and you will probably be able to figure out a solution.
William
See patrick dw's answer on how to do it :)
Stian
A: 

Have your switchBatch() function accept another argument, which is a function containing the code that you are trying to run after the AJAX request.

Then call that function in the success: callback for the AJAX request in switchBatch().

function loader(){
    if ($("#prod_1").val() > 0) {
        switchBatch(1, function() {
            $('#batch_1').val('15');
            updateMax(1); // right now this is being called in switchBatch() as well
        }
        );
    }
    if ($("#prod_2").val() > 0) {
        switchBatch(2, function() {
            $('#batch_2').val('35');
            updateMax(2);  // right now this is being called in switchBatch() as well
        }
        );
    }
}

  // function argument -------v
function switchBatch(idNum, func){
        maxVals = [];
        $("#max_"+idNum).val('');
        $.ajax({
            type: "POST",
            url: "/cfc/product.cfc?method=pialJson",
            data: ({
                productID: $("#prod_"+idNum).val()
            }),
            dataType: "json",
            success: function(result){
                options = '';
                var colMap = new Object();
                for(var i = 0; i < result.COLUMNS.length; i++) {
                    colMap[result.COLUMNS[i]] = i;
                }
                for (var i = 0; i < result.DATA.length; i++){
                    options += '<option value="' + result.DATA[i][colMap["BATCHID"]] + '">' + result.DATA[i][colMap["BATCHNAME"]]+ '</option>';
                    maxVals[i] = result.DATA[i][colMap["INSTOCK"]];
                }
                $("select#batch_"+idNum).html(options);

                  // call the function that was passed in
                func.call(null);
                updateMax(idNum); // updateMax is being called in the function that is
                                  //   passed in. You probably don't need it in both places
            }
        });
    }
patrick dw
Thanks Patrick that did the trick. Now I have to figure out why lol
Lance