0

I want the close and function to modify the variable gate, by making the padding bigger until it equals the variable open. I don't know why it won't work, please help.

function wait() {
    setTimeout(100);
}

function close() {
    var closed = 1;
    var opened = 19;
    var gate = opened;

    while (gate !== closed) {
        gate-=1;
        gate.style.paddingTop = open'%';
        wait();
    }
}
6
  • That's not how setTimeout() works. It takes two arguments, and the first one is the function to call when the timer expires. It is not a "sleep" function. Commented Apr 30, 2016 at 20:53
  • What is this supposed to do? gate.style.paddingTop = open'%';. gate is a Numeric, so gate.style is undefined. Commented Apr 30, 2016 at 20:54
  • There are a few other errors as well, like the random open'%' which I think you probably mean to be open + '%' but I'm guessing, and it's not clear what you're trying to do with gate.style. Commented Apr 30, 2016 at 20:54
  • Also, be careful with this: while (gate !== closed) {. This appears to be an infinite loop in your case. Commented Apr 30, 2016 at 20:55
  • Thank you Pointy and yes Dave Newton, you are right, thank you. Thank you Shomz, your anser was very helpfull. Commented Apr 30, 2016 at 21:07

3 Answers 3

2

Timeouts in JS are not blocking - thing of them as running in a separate thread. There are tons of resources about how they exactly work online, so I won't get into that.

To fix your code, you can refactor is to make recursive calls:

var closed = 1;
var opened = 19;
var gate = opened;
var gateEl = document.getElementById('gate');

function close() {
    if (gate !== closed) {
        gate -= 1;
        gateEl.style.paddingTop = gate + '%'; // open stays the same
        setTimeout(close, 100);
    }
}
  • make recursive calls to your close function
  • define an element which will have its padding changed
  • use gate instead of open to actually change the padding

Here's a live example:

var closed = 1;
var opened = 19;
var gate = opened;
var gateDiv = document.getElementById('gate');

function close() {
  console.log(gate);
  if (gate > closed) {
    gate -= 1;
    gateDiv.style.paddingTop = gate + '%';
    setTimeout(close, 100);
  }
}

close();
#gate {
  height: 50px;
  width: 50px;
  background: green;
}
<div id="gate"></div>

Sign up to request clarification or add additional context in comments.

Comments

1

A better implementation would be like this:

// gate element
var gate = document.getElementById("gate");
// the space between the gate and the ground
var gap = 100;
// how many pixels/percentage you want it to move at each iteration
var increment = -2;

function close() {
  // gap = 0 means it's closed
  // as long as it's not closed run this
  if (gap > 0) {
    // decrease the gap
    gap = gap + increment;
    gate.style.top = (gap * -1) + "%";
  } else {
    // gate is closed, so we clear the interval
    clearInterval(closing);
  }
}

// a reference to interval
var closing = setInterval(close, 100);
#container {
  width: 300px;
  height: 100px;
  border: 1px solid rgba(0, 0, 0, .2);
  position: relative;
  overflow: hidden;
}
#gate {
  width: 100%;
  height: 100%;
  background: brown;
  position: absolute;
  top: -100%;
}
<div id="container">
  <div id="gate"></div>
</div>

Comments

0

This is a pretty advanced topic! I highly recommend you read about Promises and async/await. Being experienced with asynchronous programming and JavaScript in general will also really help.


In the future you'll be able to use async/await to write this pretty much the same as you did:

function wait() {
    return new Promise(function(resolve) {
        setTimeout(resolve, 100)
    });
}

async function close() {
    var closed = 1;
    var opened = 19;
    var gate = opened;

    while (gate !== closed) {
        gate -= 1;
        gateEl.style.paddingTop = open + '%';
        await wait();
    }
}

This has a few different parts to it, so I'll go over each..

First, I fixed a couple of general issues with your code:

gate.style.paddingTop = open'%';
// changed to:
gateEl.style.paddingTop = open + '%';
// First, we need to join the open variable and the '%' string, so
// I add a + for that; second, gate is a number, not a DOM element,
// so I assumed there is a new variable called "gateEl" that means
// the actual element. Supply that in the actual code.

Then I implemented async/await into the code. This involved a few changes. I redefined the function wait:

function wait() {
    return new Promise(function(resolve) {
        setTimeout(resolve, 100)
    });
}

It looks kind of confusing but basically I'm making a new Promise object given a function argument. Promises are the things that make async/await work. In my wait function, when await wait() is called, resolve is called 100 milliseconds later. resolve is what says that the code after await wait() can run.

Next, I added async before function close() {...} -- that makes await work inside of it.

Finally, I replaced wait() with await wait(). This changes your browser from thinking "call the wait function" to "call the wait function, and then wait until the promise actually the then-able object it returns to resolve." And we know that the promise resolves 100ms after wait is called - because we defined it to do so.

The nice thing about await fn() is that loops and other control structures work really well with it.

Comments

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.