6

I have looked around a lot, and not found the answer yet. Maybe it is simply something that cannot be done.

I am new to jQuery and JavaScript. Just to test the limitations I am trying to create a script that will continuously append a list item to an un-ordered list while a check box is not checked. I know I may not have my while statement correct in searching if the checkbox is checked or not, but the main issue I am having at the moment is the while loop starts running faster than the browser can keep up, locks up the page, and eventually I have to kill the browser. I have read many examples on setTimeout and setInterval, but what I continuously see is those only work with a for/next style loop, where the loop goes for a predetermined amount of cycles dependent upon a variable. I do not want this. I want the loop to continue until I check the box and then it should stop. So I am looking for a way to pause the loop or slow it down so 1) I can see each list item appended to the page, and 2) the script will give me a chance to end it by checking the box before it runs the browser to freeze/suicide.

Thanks in advance, code is below.

$(function(){
    $(document).ready(function() {loopLi();});
        var i = $('#jlist li').size();
        console.log(i);

        function loopLi() {
            while($('#Chckbox').not(":checked") ) {
                setInterval(function(){
                    i++;
                    $('<li>' + i + '</li>').appendTo('#jlist');
                }, 5000);
            }
        }
});

EDIT: Thank you all. Got it working. Did not realize that a while loop would run the code multiple times at the same time. This is all being learned for work, and the book we currently have does not go this in depth with stuff. Currently using jQuery: Novice to Ninja. Anything else we should look at to answer these kinds of questions, or is this just something that comes with working with it?

JHStarner
  • 173
  • 1
  • 2
  • 13
  • 1
    Just so you understand why your code was freezing your browser: you were executing the setInterval function in the while loop, so millions of setInterval function calls were being made, so you added millions of timers to your page, which froze your browser. The moral of this story is, don't execute an asynchronous call in an (practically) infinite loop. – ironchefpython Jul 13 '11 at 17:13

4 Answers4

13

You're now creating an infinite amount of intervals - as long as the while loop is executed it creates a new one and the browser is therefore always busy and cannot respond to a checkbox click. Just one interval is enough.

Also, you ought to use ! .is() because .not returns a jQuery object, which is always truthy, i.e. passing the if/while.

http://jsfiddle.net/rUAKx/

var i = 0;

function loopLi() {
    setInterval(function() { // this code is executed every 500 milliseconds:

        if(!$('#Chckbox').is(":checked")) {
            i++;
            $('<li>' + i + '</li>').appendTo('#jlist');
        }

    }, 500);
}

$(loopLi);
pimvdb
  • 151,816
  • 78
  • 307
  • 352
  • This worked excellently. I am now worried about what someone says below though. Something about clearing the interval. Is that something that has to be done if I am going to do something else, or what does that mean? – JHStarner Jul 13 '11 at 18:42
  • @JHStarner: What I'm doing is running the interval always and checking each time whether or not to append a `li`. You can also clear the interval when the checkbox is not checked. Then the interval will always append a `li` but the interval will not be run if it's unchecked. – pimvdb Jul 13 '11 at 18:49
  • @JHStammer: Let me try to explain it again :) There are two possibilities: 1) Check every 5 seconds whether the checkbox is checked and if so, append a `li`. 2) When you check the checkbox, create an interval that appends a `li` every 5 seconds. When you uncheck it again, stop that interval. – pimvdb Jul 13 '11 at 19:27
  • Ok let me make sure I got it. The code you gave says: "We have a var of i that equals 0. Now we start this function loopLi. Over the next half second run this (check if box is not checked, if so increment i and append). Finished the code, pull up the next function loopLi." So this means that that script is running every half a second until the page is killed? If so, I got the desired result but now things are not working efficiently. If it is going to pull $(loopLi); for as long as the page is open, even when checked, doesn't that make this something that will slowly eat up memory? – JHStarner Jul 13 '11 at 19:44
  • @JHStarner: It might eat up bits of memory theoretically, but JavaScript has a 'garbage collector' built in that automatically cleans up inaccessible variables. So the second time the interval is called, the memory of the first time can be cleaned up automatically. Also, every 5 seconds cannot be a bottleneck with so little code. – pimvdb Jul 13 '11 at 20:29
  • Why do you need jQuery for this though? You could do `var loopLi = setInterval(function() { ... }, 500);` and then you could either call `clearInterval(loopLi);` to stop it or put that call inside the `function` code to automatically stop it when a condition is reached. – ADTC Aug 17 '20 at 12:26
3

I'm guessing you want to do something similar to this:

http://jsfiddle.net/PsXEa/5/

$(function(){
    i = $('#jlist li').size();
    console.log(i);

    function loopLi() {
        if ($('#Chckbox').not(":checked") ) {
            i++;
            $('<li>' + i + '</li>').appendTo('#jlist');
            setTimeout(loopLi,1000);
        }
    }
    loopLi();
});

Note that you've got a lot of similar solutions here. You should select one that either uses a setTimeout call explicitly in the loop, or that cleans up their setInterval timer with clearInterval.

ironchefpython
  • 3,409
  • 1
  • 19
  • 32
0

You can use the clearInterval to stop executing the append process when the user checks the checkbox. Try this:

$(function(){
       var intObj = null;
  $(document).ready(function() {loopLi();});
        var i = $('#jlist li').size();
        console.log(i);
        function loopLi() {
            intObj = setInterval(function(){
            i++;
            $('<li>' + i + '</li>').appendTo('#jlist');
          }, 5000);
        }
        $('#Chckbox').click(function(){
            if(this.checked){
             clearInterval(intObj );
            }
        });
});
Chandu
  • 81,493
  • 19
  • 133
  • 134
0

Here's a working revision. Basically, loopLi will add the item only until the checkbox is checked. I sped it up so you can see it better.

http://jsfiddle.net/TrowthePlow/WkstU/

josh.trow
  • 4,861
  • 20
  • 31