Alex D'ago
Alex D'ago

Reputation: 162

How to move a div with javascript

I am definitely new to Javascript.My goal is to build two divs and animate the child just by using Javascript.But there is some kind of problem in my function, and despite this being a trivial task I couldn’t find anything.

So, these are my buttons and my divs(I’m just trying to figure out how the start button works, then I am going to deal with the others

//create elements
const start = document.createElement('button');
const reset = document.createElement('button');
const stop = document.createElement('button');



const parent = document.createElement("div");
const child= document.createElement("div");
document.body.append(parent);
parent.append(child);
document.body.append(start);
document.body.append(reset);
document.body.append(stop);

// style 
parent.style.width = "200px";
parent.style.height = "200px";

child.style.width = "20px";
child.style.height = "20px";


child.style.background = "green"
parent.style.background  = "red";

start.innerHTML = "start";
reset.innerHTML = "reset";
stop.innerHTML = "stop";

and this is my useless function which doesn’t look right

/functions and listeners
var g =setInterval(move(),2000);
function move(){
    var pos = 0;
    if (pos == 200) {
        clearInterval(g);
    }
    else {
        pos++;
        child.style.top = pos + "px";
        child.style.left = pos + "px";
    }
}
start.addEventListener("click",move());

any kind of tip or advice is appreciated =)

Upvotes: 0

Views: 81

Answers (1)

Scott Marcus
Scott Marcus

Reputation: 65806

You have several problems:

  • The pos variable needs to be declared outside of the function that uses it so that its value won't be lost when the function runs and then can be used when the function runs additional times.
  • The start button's click event handler should be where the interval timer is started, otherwise it begins immediately.
  • Both setInterval() and .addEventListener() take function references - - you do not invoke a function in their arguments (unless that function returns a function and that returned function is what you want to reference). So, neither should have () after the function name.
  • Your parent and child elements need to be positioned so that they are not in the normal document flow, otherwise setting a top or left CSS property won't do anything.
  • Don't use .innerHTML when you aren't working with HTML strings as .innerHTML has security and performance implications. When you just have text to work with, use .textContent.

See other comments inline:

//create elements
const start = document.createElement('button');
const reset = document.createElement('button');
const stop = document.createElement('button');

const parent = document.createElement("div");
const child= document.createElement("div");
document.body.append(parent);
parent.append(child);
document.body.append(start);
document.body.append(reset);
document.body.append(stop);

/* Use CSS classes instead of inline styles */
parent.classList.add("parent");
child.classList.add("child");

start.textContent = "start";
reset.textContent = "reset";
stop.textContent = "stop";

//functions and listeners
var timer = null;
var pos = 0;
function move(){
  // Since it's the top and left of the child that are being set, we
  // need to subtract the width of the box from the size of the parent
  // so that the child doesn't end with its top and left outside of the
  // parent.
  if (pos == 180) {
    clearInterval(timer);
  } else {
    pos++;
    child.style.top = pos + "px";
    child.style.left = pos + "px";
  }
}
start.addEventListener("click", function() {
  // The timer should start when the button is clicked
  timer = setInterval(move,20);
});

reset.addEventListener("click", function() {    
  clearInterval(timer); // Stop the timer so motion stops
  pos = 0;     
  child.style.top = pos+ "px";     
  child.style.left = pos + "px";      
});
/* The child needs to be taken out of the normal document flow so it can be
   explicitly positioned, but we want it to be relative to the parent it is
   inside of, so the parent also has to be positioned explicitly.  */
.parent { position:relative; width: 200px; height:200px; background-color:red; }
.child { position:relative; width: 20px; height:20px; background-color:green; }

Upvotes: 1

Related Questions