views:

40

answers:

2

I've written some javascript using jQuery to replace any select lists with a div and ul alternative so that it will give me some more styling control and make the drop downs look the same cross browser. The below code works 99% for me but I have one issue. At the bottom of the code I have had to use .delay() to tell the code in a way to wait for the .each() loop above to finish doing what its doing. The problem with this is that there is atleast one second untill the replacement happens leaving a flash of the old select boxes. Also I can forsee another problem is what if it takes more than one second for the each() loop to complete...

How can I get the code at the bottom to only run once the each loop has run and complete. Also I welcome any optimizations on the rest of the code.

EDIT: Some of the HTML has been stripped from the code so I have pastebinned it: http://pastebin.com/4HFLjHE1


// Check when ready
$(function() {

    // Find dropdowns
    $("select.dropdownreplace").each(function() {replaceDropDown(this);});
    // If document clicked anywhere hide drop downs
    $(document).click(function(event){
        $("div.dropdownreplace ul").hide();
    });

});

function replaceDropDown(that) {
    // Create HTML for new drop down
    // hidden field
    var hiddeninput = $('');
    // div
    var dropdowndiv = $(''+$(":selected", that).text()+'
    '); // loop through values and make li's $("option", that).each(function() { $("ul", dropdowndiv).append('
  • '+$(this).val()+''+$(this).text()+'
  • '); // set click handler for this drop down $(dropdowndiv).click(function() { $("ul", this).show(); return false; }); // set click handler for link items $("a", dropdowndiv).click(function() { // Get name of hidden input var nameofdropdown = $(this).parent().parent().parent().attr('id'); var nameofinput = nameofdropdown.replace("dropdownreplacement_", ""); // set hidden input value to whats been clicked $("[name='"+nameofinput+"']").val($(this).parent().find("span").text()); // set div $("div#"+nameofdropdown+" > span").text($(this).text()); $("div#"+nameofdropdown+" ul").hide(); return false; }); }); // Remove drop down then add in replacement html $(that).delay(1000).after(hiddeninput); $(that).delay(1100).after(dropdowndiv); $(that).delay(1200).remove(); }

    Thnaks

    Scott

    +1  A: 

    What you have to do is create a callback functionl. In your each(), after the initial function you can indicate it has to do some more things when it's finished:

    $("option", that).each(function() {
    
      <...code...>
    
    }, function() {   
          <...code...>  //this gets performed after the previous function is complete
    });
    
    Litso
    So you saying do this: http://pastebin.com/DL5CW5EP but that doesnt work
    Brady
    hmm, yeah I thought it would. Sorry, I don't have time to try and fix it right now, maybe later. Hopefuly someone else can help.
    Litso
    +1  A: 

    Inside your function, compare the index jquery passes you, with the total number of items you have.

    I don't know your html, but I believe you can do this.

    Change your function so it receives the index param that jquery sends.

    $("option", that).each(function(index) {
    

    Then, at the end of that function compare the length with the index, if they are the same, then you're done

    if ( $('option', that).length == (index +1 ) ) {
        $(that).after(hiddeninput);
        $(that).after(dropdowndiv);
        $(that).remove();
    }
    

    From my tests, this should be what you need. Don't know if there is a more "standard" way to do it.

    Hope this helps

    Leite
    Thanks! I don't know why I didn't think of this. I've had similar issues like this before and managed to work them but this time I was convinced there wasnt a better way than I already did it....
    Brady