2

Yeah, I know, likely been answered, but can't find it or figure out how to successfully search for it, so, 45 minutes later i am succumbing to the potential of flaming...so go easy on me, ok?

It is a simple problem, and my issue is timing. One select holds Countries, it is bound to State/Province select. Change Country, State/Province loads appropriately via a separate function. Use a mouse to select from State/Province, perfection. Use JavaScript ..uh oh. Problem is I need to force my JavaScript to wait for the browser to load the State/Province data before I can target and select it. SetTimeout or using a Promise just seems... inelegant? How many seconds does a browser need to load 50 states or 8 provinces - on a new rocket or an old turtle? Is there a way to just know when the second select finishes loading when the load is in a separate function? Example is jquery, but any flavor will do.

$('#country option[value=US]').prop('selected', 'selected').change();
$('#stp option[value=VT]').prop('selected', 'selected').change();

Adding more clarification based on the responses so far.

Whena user changes the Country, the State/Province loads in the time it takes them to move their mouse down the page allowing them to select. Now I have implemented a helper that pulls the user's address from BigData using a phone number. This happens in a dialog box. When the user clicks "Accept" this code then fires

function setFormwithDF(){
    d={};
    // data from dialog
    d.address=$('#oaddress').text();
    d.city=$('#ocity').text();
    d.state=$('#ostate').text();
    d.zip=$('#ozip').text();
    d.country=$('#ocountry').text();

    $('#s_country option[value='+d.country+']').prop('selected', 'selected').trigger('change');
    // doesn't matter if this is .change() or .trigger('change')
    $('#s_addr1').val(d.address).change();
    $('#s_addr2').val('').change();
    $('#s_city').val(d.city).change();
    $('#s_st option[value='+d.state+']').delay(3000).prop('selected', 'selected');console.log(d.state);//getting a good value here - delay is desperation
    $('#s_zip').val(d.zip);
    $('#s_phone').val($('#dfsearch').val());
    $( "#dfsearchdialog" ).dialog('close');
   }

And for completeness, here is the loading code. Bunch of extras in here that don't pertain to the issue though

$('#s_country,#b_country').change(function(e){
    var st="";
    var addrType="S";
    var loadObj=$('#shipstp');
    if( $(this).attr("id") == 'b_country'){
      loadObj=$('#billstp');
      addrType="B";
    }
    if( typeof(e.st) != 'undefined'){st=e.st;console.log(5)}// this data is passed during the trigger() code
    uObj={c:$(this).val(),nc:Math.random(),t:addrType,p:st};
    uParam=$.param(uObj);
    loadObj.load('/stubs/state-n-province.cfm',uParam);
});
0

2 Answers 2

0

As per my understanding, you dont want user to select state until the state's are getting loaded. After loading only user should be able to select the state.

And I am assuming you are using AJAX to load the State.

If this is the issue :

you can use loading image, which will be displayed until the success has not been return and data has not been map to element.

In this case you can use below sample code :

function getData(p){
    .......
    $('#loadingmessage').show();  // show the loading message.
    $.ajax({
    url: "loadData.php?id=<? echo $id; ?>",
    type: "POST",
    cache: false,
    data: "&page="+ page,
    success : function(html){
        $(".content").html(html);
        $('#loadingmessage').hide(); // hide the loading message
    }
});
Sign up to request clarification or add additional context in comments.

2 Comments

nope, not the problem. When a user interacts, everything works as planned. But when County change is triggered with JavaScript, the State cannot be selected with javascript until the select finishes loading. And the loading function is a seperate function
Can u post the code, so I can actually see the flow
0

I believe a Promise is what you need. It will allow you exactly

to just know when the second select finishes loading when the load is in a separate function

$('#country').change(function() {
    $("#stp").empty().append("<option>...</option>");
    loadStates($(this).val())
        .then(states => $("#stp")
            .empty()
            .append(states.reduce((acc, cur) => acc + `<option>${cur}</option>`, "")));
});


$('#country').change();

function loadStates(country) {
    console.log(`Loading states for country: ${country}...`); 
    //setTimeout here just emulates your long loading process
    return new Promise((res, rej) => setTimeout(() => {
            console.log(`States for country: ${country} are loaded!`); 
            res(["state1", "state2", "state3"]);
        }, 3000));
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<select id="country">
   <option>US</option>
   <option>UK</option>
   <option>RU</option>
</select>

<select id="stp">
</select>

For your actual use case you would write something like:

return new Promise((resolve, reject) => {
    var states = yourLoadingFunction();
    resolve(states);
});

UPDATE: Given your latest example, I think I understand your problem now. I suggest you to put your loading code into a separate function, for example:

function countryChanged(e, callback) {    
    var st="";
    var addrType="S";
    var loadObj=$('#shipstp');
    if( $(this).attr("id") == 'b_country'){
      loadObj=$('#billstp');
      addrType="B";
    }
    loadObj.prop("disabled", true);
    // this data is passed during the trigger() code
    if( typeof(e.st) != 'undefined'){st=e.st;console.log(5)}
    uObj={c:$(this).val(),nc:Math.random(),t:addrType,p:st};
    uParam=$.param(uObj);
    loadObj.load('/stubs/state-n-province.cfm', uParam, function() {
        // when the loading is complete, we enable the second select and 
        // call the callback function
        loadObj.prop("disabled", false);
        if (callback) callback();
    });
}

Note that jQuery .load() method has a third argument which is a callback function that will be called when the loading is complete.

Then you can use this function in two ways:

1) when the user changes the country:

$('#s_country,#b_country').change(countryChanged);

2) in your setFormwithDF() function:

function setFormwithDF(){
    d={};
    // data from dialog
    d.address=$('#oaddress').text();
    d.city=$('#ocity').text();
    d.state=$('#ostate').text();
    d.zip=$('#ozip').text();
    d.country=$('#ocountry').text();

    $('#s_country option[value='+d.country+']').prop('selected', 'selected');
    //instead of calling .trigger('change') just call countryChanged function
    countryChanged({st: "whatever you pass during the trigger() code"}, function() {
       //this will happen only after .load() is complete
        $('#s_st option[value='+d.state+']').prop('selected', 'selected');
    });
    $('#s_addr1').val(d.address).change();
    $('#s_addr2').val('').change();
    $('#s_city').val(d.city).change();
    $('#s_zip').val(d.zip);
    $('#s_phone').val($('#dfsearch').val());
    $( "#dfsearchdialog" ).dialog('close');
}

5 Comments

all Promise is, is a timeout. What do I set it for? And what about Safari and IE?
@MikeG Promise is not a timeout, it's an async executor. It allows you to execute some task exactly when some other task finishes, no matter how much time is passed. So I thought that it is what you need. What about Safari and IE... Well, for IE you have to use some polyfill, and Safari supports Promises
ok, I will dig a bit deeper. But... from what I have read so far, I don't see how this is going to solve the problem. Looks like I need to change the loading function, but in your example the console logs way before the select finishes loading. I need to create the pause in my setFormwithDF() function between Country and state actions. Can you tweak your code so that the console loads after the select finishes loading?
@MikeG sure! check the update. I've added an example of how you could use your loading function
@MikeG I noticed that you use jquery .load function which has a callback argument. It could be helpful in your situation. Check my update

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.