update a JQuery progress bar added at runtime

2019-06-21 20:19发布

问题:

I'm having some problems updating a jquery progress bar. This progress bar isn't in the document during the page load, I'm adding it just when the user click on a button, ding something like this:

$(this).parent().append('<div class="progressbar"></div>');
$(this).parent().children('div.progressbar').show();
$(this).parent().children('div.progressbar').progressbar({value: 20});

then, using a timeout, I'm trying to update it

function updateProgressBar() {
    $('.progressbar').each(function() {
        myNewValue = getNewValue();
        $(this).progressbar('value', 50);
    });
    setTimeout('updateProgressBar()', 5000);
}
setTimeout('updateProgressBar()', 5000);

the debug console complains saying: "Uncaught: cannot call methods on progressbar prior to initialiaztion: attempted to call method 'value'" Googling here I found that the problem could be related to the inizialization of the progress bar after the loading of the page

Could someone help me?

Thanks in advance

-- edit --

thanks Bryan, I'm trying your solution but i doesn't work for me

Now I've this code

function startProgress() {

    $(this).parent().append('<div class="progressbar"></div>');
    $(this).siblings('.progressbar').show();
    $(this).siblings('.progressbar').progressbar({value: 0});

    function updateProgress() {
        $('.progressbar').each(function() {
            myNewValue = getNewValue($(this).parent().parent().attr('id'));
            $(this).progressbar('value', myNewValue);
        });
        setTimeout('updateProgress', 5000);
    }
    setTimeout('updateProgress', 5000);
}

The console is sayng there's no updateProgress defined

-- edit --

many many thanks!!!

Now i've a quite definitive version that works...

Here my current code

if($(this).siblings('.progressbar').size() == 0) {
        $(this).parent().append('<div class="progressbar"/>');
        $(this).siblings('.progressbar').progressbar({value: 0});
}
$(this).siblings('.progressbar').show();

function updateProgress() {
    $('.progressbar').each(function() {
        myParams = 'service=' + $(this).parent().parent().attr('id') + '&content=' + $(this).parent().attr('id')
        myUrl = '/datacast/content_progress/?' + myParams;
        theValue = $(this).progressbar('value');
        $.get(myUrl, {}, function(aReply) {
            myData = aReply.split(' ');
            myItemId =  myData[0];
            myValue = parseInt(myData[1]);
            try {
                $(".item[id = " + myItemId + "]").children(".progressbar").progressbar('value', myValue);
            }
            catch(myError) {
                //alert(myError);
            }
        })
    });
    setTimeout(updateProgress, 5000);
}
setTimeout(updateProgress, 5000);

As you can see I've add a control if there is already a progress bar as i pass thorough that code several times. The progress bar is updated every time, but the console complains saying "TypeError: Cannot call method 'apply' of undefined", so I had to add the try block with an empty catch body to drop the error. The page works but it could be interesting if you have an idea why there's that error

回答1:

Had the same problem

Apparently you must use the format progressbar({value:30}) the first time

If you use progressbar(value,30) the first time then you get this exception.



回答2:

Ok, I can't believe I missed that. The problem is that you're passing a string to the setTimeout function. This will cause it to lookup the name of the function in global scope, which it's not.

Change both of these calls:

setTimeout('updateProgress', 5000);

to

setTimeout(updateProgress, 5000);


回答3:

Make sure that you're using the exact same selector in your update method as in the initialization method.

In the provided code, you're doing something like $(this).parent().children().find('.progressbar') and then in the update you're just doing $('.progressbar'). That second call could potentially return items that the first one didn't, and those items wouldn't have a progress bar initialized.

This code worked fine for me:

$(function(){
    $('body').append('<div class="progress"></div>');

    var val = 10;
    $('.progress').progressbar({value:val});

    function updateProgress() {
        val += 10;
        $('.progress').progressbar('value', val);
        if(val < 100)
            setTimeout(updateProgress, 1000);
    }

    setTimeout(updateProgress, 1000);
});

Also, remember that you don't actually need that call to each() as jquery methods should automatically apply to all elements matched with that selector.

Example:

$('.red').each(function(){ $(this).css({color:'red'}); });

is redundant, and the same can be achieved with:

$('.red').css({color:'red'});

Oh, and here's a freebie:

$(this).parent().children().find('.progressbar')

can be shortened to: $(this).siblings('.progressbar')