Search code examples
for-loopsliderjsxgraph

How can I use a slider to return the number of times a loop is to be performed?


This smidgen of code (assuming a board has been defined of appropriate size), gives the idea of what I'm trying:

 var s = board.create('slider',[[1,-1],[5,-1],[0,0,10]],{name:'s',snapWidth:1});
 for (let i = 0; i <= s.Value(); i++) {
    var p = board.create('point',[()=>{return i-5;},()=>{return Math.pow(i-5,2)/5;}]);
    }

The loop works fine if I replace s.Value() with a number; say 10. But I want the number of points to be plotted to be defined by the slider value.

I've also tried replacing s.Value() with function(){return s.Value();} but that doesn't work either. Any ideas? Thanks!


Solution

  • The code is working nearly correct, but does not do what you intend: The line

    var s = board.create('slider',[[1,-1],[5,-1],[0,0,10]], {name:'s',snapWidth:1});
    

    creates a slider and initializes it with the value 0 (the second value in the last array). Then, in the subsequent for-loop the slider value is used:

    for (let i = 0; i <= s.Value(); i++) {
      var p = board.create('point',[()=>{return i-5;},()=>{return Math.pow(i-5,2)/5;}]);
    }
    

    The loop effectly reads for (let i = 0; i <= 0; i++) {}. Actually, one point should have been created, but a small numerical error probably prohibits even this.

    But anyhow, this is not what you want to do, since the loop is executed only once, namely at initialization time. So far, the code does not react to dragging the slider by the user, i.e. has no event listener registered.

    My suggestion would be to create at initalization time all points in a loop, hide them (visible:false) and store them in an array. Then, we add an event listener which reacts to dragging of the slider. In that event listener method, we set all points with index <= s.Value() visible and the others invisible. The code looks like this:

    var points = [];
    for (let i = 0; i <= 10; i++) {
      points.push(
        board.create('point',[
          ()=>{return i-5;},()=>{return Math.pow(i-5,2)/5;}
        ], {
          visible:false, 
          label: { visible: false }
        })
      );
    }
    
    s.on('drag', () => {
      for (let i = 0; i <= 10; i++) {
        if (i <= s.Value()) {
          points[i].setAttribute({visible:true});
        } else {
          points[i].setAttribute({visible:false});
        }
      }
    });
    

    See it live at https://jsfiddle.net/67d9brcm/2/.