can't change parent element properly in javascript - javascript

I have two div elements, in the first one I put three buttons. here is the code
it works properly but the problem is in reset button (it should move all the buttons to start div) when I press it just moves 2 elements back to the starting div. what can be a problem?
function move(element){
let newParent = document.querySelector('#favourites');
newParent.append(element);
}
function reset(){
let startingDiv = document.querySelector('#startingArea');
let favouritesDiv = document.querySelector("#favourites");
var children = favouritesDiv.children;
for(var i=0;i<children.length;i++){
startingDiv.append(children[i]);
}
}
<html>
<head>
<script src="script.js"></script>
</head>
<body>
<h1>Click on your favourite wrestler<h1>
<div id="startingArea">
<button onclick='move(this)' id="cena1">John Cena</button>
<button onclick='move(this)' id="cena2">Jooohn Ceenna</button>
<button onclick='move(this)' id="cena3">JOoOoOOoooOooOOooOohn CeeeeeeEEEnaaaaaaa</button>
</div>
<h3>Your Favourite Wrestlers</h3>
<div id="favourites">
</div>
<br><br><br>
<button onclick="reset()">reset</button>
</body>
</html>

You can use the following code for the reset function and it should work:
function reset(){
let startingDiv = document.querySelector('#startingArea');
let favouritesDiv = document.querySelector("#favourites");
while(favouritesDiv.firstChild) {
startingDiv.append(favouritesDiv.firstChild);
}
}

You need to convert the HTMLCollection you get from the "children" property into a standard array and it works:
var starter = document.querySelector('#startingArea');
var childrenCollection = document.querySelector("#favourites").children;
var children = Array.prototype.slice.call(childrenCollection);
for(var i=0;i<children.length;i++){
starter.append(children[i]);
}

In simple way you can do this way.
function reset() {
let startingDiv = document.querySelector('#startingArea');
let favouritesDiv = document.querySelector("#favourites");
startingDiv.innerHTML = favouritesDiv.innerHTML;
favouritesDiv.innerHTML = "";
}

Related

Why is the done button not working properly?

Apparently I'm trying to create a todo list where I can ofcourse add and remove the tasks. Adding tasks works fine; however clicking on the Done Button works but doesn't do what I want it to do. Basically I have a Logical Error, but I don't know what to do to fix it.
The Code
<!DOCTYPE html>
<html lang="en">
<head>
<title>Document</title>
</head>
<body>
<h1>To-Do List</h1>
<form id="todoForm">
<input id="todoInput" />
<button type="button" onclick="todoList()">New</button>
<button type="button" onclick="">Retrieve</button>
</form>
<ol id="todoList"></ol>
<script>
var todos = []; //Problem is from here
var removed = [];
function todoList() {
var item = document.getElementById("todoInput").value;
todos.push(item);
var text = document.createTextNode(item);
var newItem = document.createElement("li");
newItem.innerHTML = item + ' <button id="Done">Done</button>';
document.getElementById("todoList").appendChild(newItem);
const donebtn = document.getElementById("Done");
donebtn.addEventListener("click", function() {
removetodo(newItem, item)
});
}
function removetodo(item, tasktext) {
const tasklist = document.getElementById("todoList");
tasklist.removeChild(item);
removed.push(tasktext);
}
</script>
</body>
</html>
Thing is, I tried finding solutions to it on Google and other places; yet, I still didnt know how to fix it. I dont want to just change the whole code so it could work. I specifically wanted it in the way I wrote it in
newItem.innerHTML = item + ' Done'; I changed this line the problem was that you are assigning the same id's to all done so I used a count variable which is at the start 0 when you run function if will 0 like done0 when the function run it will increase count++ will increase it next time it will be done1 so your code will work correctly
<!DOCTYPE html>
<html lang="en">
<head>
<title>Document</title>
</head>
<body>
<h1>To-Do List</h1>
<form id="todoForm">
<input id="todoInput" />
<button type="button" onclick="todoList()">New</button>
<button type="button" onclick="">Retrieve</button>
</form>
<ol id="todoList"></ol>
<script>
var todos = []; //Problem is from here
var removed = [];
let count = 0;
function todoList() {
var item = document.getElementById("todoInput").value;
todos.push(item);
var text = document.createTextNode(item);
var newItem = document.createElement("li");
newItem.innerHTML = item + ' <button id="Done'+count+'">Done</button>';
document.getElementById("todoList").appendChild(newItem);
const donebtn = document.getElementById("Done"+count);
donebtn.addEventListener("click", function(){
removetodo(newItem, item)
});
count++;
}
function removetodo(item, tasktext) {
const tasklist = document.getElementById("todoList");
tasklist.removeChild(item);
removed.push(tasktext);
}
</script>
</body>
</html>
one more suggestion
newItem.innerHTML = item + ' <button id="Done'+count+'">Done</button>';
document.getElementById("todoList").appendChild(newItem);
const donebtn = document.getElementById("Done"+count);
donebtn.addEventListener("click", function(){
here in your code const donebtn = document.getElementById("Done"+count); you don't need this line just donebtn.addEventListener("click", function(){ here insted of donebtn you can use newItem.addEventListener and then append it
document.getElementById("todoList").appendChild(newItem); at the last use this.
newItem.innerHTML = item + ' <button id="Done'+count+'">Done</button>';
newItem.addEventListener("click", function(){}
document.getElementById("todoList").appendChild(newItem);
like this
This code will only run when your function is called.
const donebtn = document.getElementById("Done");
donebtn.addEventListener("click", function() {
removetodo(newItem, item)
});
you should put it outside the functions to attach the listener.
The first issue with the code is that when you remove the task from the list, it's not actually removing it from the todos array. To fix this, you can add the following line after removing the task from the list:
todos.splice(todos.indexOf(tasktext), 1);
The second issue is that you are using the same id for all the "Done" <button> elements, in the HTML markup, IDs should be unique. So when you use document.getElementById("Done"), it always returns the first element with that id.
To fix this issue, you can use a class instead of an id and query for all elements with that class and attach an event listener to each button individually.
Updated code:
<!DOCTYPE html>
<html lang="en">
<head>
<title>Document</title>
</head>
<body>
<h1>To-Do List</h1>
<form id="todoForm">
<input id="todoInput" />
<button type="button" onclick="todoList()">New</button>
<button type="button" onclick="">Retrieve</button>
</form>
<ol id="todoList"></ol>
<script>
var todos = [];
var removed = [];
function todoList() {
let item = document.getElementById("todoInput").value;
todos.push(item);
let text = document.createTextNode(item);
let newItem = document.createElement("li");
newItem.innerHTML = item + ' <button class="doneBtn">Done</button>';
document.getElementById("todoList").appendChild(newItem);
const donebtn = newItem.getElementsByClassName("doneBtn")[0];
donebtn.addEventListener("click", function() {
removetodo(newItem, item);
});
}
function removetodo(item, tasktext) {
const tasklist = document.getElementById("todoList");
tasklist.removeChild(item);
removed.push(tasktext);
todos.splice(todos.indexOf(tasktext), 1);
}
</script>
</body>
</html>
Each time a new task is added, all the "Done" buttons have the same id, which is not allowed in HTML as id values must be unique within a page. This means that only the first "Done" button will respond to the click event, and all the others will be ignored.
One way you can try is to store the task text in a data attribute of the "Done" button, and use it in the removetodo function to identify the task to remove like so ...
<!DOCTYPE html>
<html lang="en">
<head>
<title>Document</title>
</head>
<body>
<h1>To-Do List</h1>
<form id="todoForm">
<input id="todoInput" />
<button type="button" onclick="todoList()">New</button>
<button type="button" onclick="">Retrieve</button>
</form>
<ol id="todoList"></ol>
<script>
var todos = [];
var removed = [];
function todoList() {
var item = document.getElementById("todoInput").value;
todos.push(item);
var text = document.createTextNode(item);
var newItem = document.createElement("li");
newItem.innerHTML = item + ' <button class="Done">Done</button>';
document.getElementById("todoList").appendChild(newItem);
const donebtn = newItem.getElementsByClassName("Done")[0];
donebtn.addEventListener("click", function() {
removetodo(newItem, item)
});
donebtn.setAttribute("data-task", item);
}
function removetodo(item, tasktext) {
const tasklist = document.getElementById("todoList");
tasklist.removeChild(item);
removed.push(tasktext);
}
</script>
</body>

Why my function to change a grid element to the size of an input of type range doesn't work?

I'm trying to create an Etch-a-Sketch project, I was going well (I think) until start to create a function that apply another size to my grid element, how can I do my function setSize() reads my function showSize() value?
Explanation:
My function showSize() shows the value of a range input element, and I need to apply this value to my function populateBoard(), so I have created setSize() function to do that, Am I right creating this intermediary function to do that?
These are my codes:
function populateBoard(size){
let board = document.querySelector(".board");
board.style.gridTemplateColumns = `repeat(${size}, 1fr)`;
board.style.gridTemplateRows = `repeat(${size}, 1fr)`;
for (let i = 0; i < 256; i++) {
let square = document.createElement("div");
square.style.backgroundColor = "green";
board.insertAdjacentElement("beforeend", square);
}
}
populateBoard(16);
function showSize(value) {
let boardSize = document.querySelector(".show-size").innerHTML = value;
}
function setSize(boardSize) {
let setSize = document.querySelector(".set");
setSize.addEventListener("click", () => {
populateBoard(boardSize);
});
}
<!DOCTYPE html>
<html>
<head>
<title>
Etch-a-Sketch
</title>
<meta charset="utf-8">
<link rel="stylesheet" href="styles.css">
<script src="script.js" defer></script>
</head>
<body>
<div class="container">
<div class="board">
</div>
<div class="settings">
<button class="clear">Clear</button>
<input type="range" min="8" value="16" max="128" step="8" oninput="showSize(this.value)">
<span class="show-size">16</span>
<button class="set">Set</button>
</div>
</div>
</body>
</html>
The problem is that you are defining the boardSize variable in the showSize function so that variable is only available in the scope of that function. Please read the following:
https://www.w3schools.com/js/js_scope.asp
I suggest you do the following.
document.querySelector(".set").addEventListener("click", () => {
let boardSize = document.querySelector(".show-size").innerHTML;
populateBoard(boardSize);
});
function setSize(value) {
document.querySelector(".show-size").innerHTML = value;
}
Some errors you have is setting the event listener in a function.
I would just have a function to set the board size as seen above and then the event listener to populate the board onclick of the set size button.

Javascript reusing forms

I want to get the names of the n (say n==5) children of a given person, by using the same form each time.
I can't seem to be able to produce javascript code that will accomplish this simple task.
for (var i = 0; i<5; i++){
<form id="child_form">
Child name:
<input type="text" id="child_name" name="child_nm" size="40">
<br>
<input type="button" value="Submit" onclick="myFunction()">
</form>
}
<script language="javascript">
<script>
function myFunction() {
add_child_to_array();
}
var array_of_children = [];
function add_child_to_array(){
var input_string = document.getElementById("child_name").value;
alert(input_string);
array_of_inputs.push(input_string);
}
</script>
But clearly one can't do that.
I've tried taking the data out of the form and then resetting the form. It turns out you can do either but not both.
I haven't found a website that deals with this problem.
Help would be greatly appreciated.
You have multiple options to accomplish this task. I would prefer to use the HTML5 template element functionality.
You could alternatively create and append the DOM Elements by yourself.
This is certainly a bit of a mess. Assuming I understand correctly, you need to create the form in javascript, so it can be dynamically added as many times as you want. I have written a generalised way of doing this. You may want to change / simplify it. I have made sure all elements are dynamic so that can be accessed properly. Also, I have used JQuery which I highly suggest.
<!DOCTYPE html>
<html>
<head>
<title></title>
<script src="https://code.jquery.com/jquery-1.11.3.js"></script>
<script type="text/javascript">
$(function(){
var allForms = document.getElementById("all-forms");
for(var i = 0;i<5;i++){
form = document.createElement("div");
form.id = "form-" + i.toString();
if(i!=0){
form.style.display = "none";
}
input = document.createElement("input");
input.id = "child_name"+i;
input.placeholder = "input"+i;
submit = document.createElement("button");
submit.innerHTML = "go"+i;
submit.id = "submit-"+i;
submit.className = "buttons";
form.appendChild(input);
form.appendChild(submit);
allForms.appendChild(form);
}
$(".buttons").click(function(){
var id = $(this).attr("id").substring(7);
$("#form-"+id).hide();
var nextID = (parseInt(id)+1).toString();
$("#form-"+nextID).show();
});
});
</script>
</head>
<body>
<div id = "all-forms"></div>
</body>
</html>

Javascript showing wrong results

HTML code
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" type="text/css" href="score-board.css">
<title>Score Board App</title>
</head>
<body>
<div id="playersscores">
<span id="p1score">0</span><span> To </span> <span id="p2score">0</span>
</div>
<p>Playing to <span id="score">5</span></p>
<input type="field" value="5" ></input>
<button id="p1clicked">Player one</button>
<button id="p2clicked">Player two</button>
<button id="reset">Reset</button>
<script type="text/javascript" src="score-board.js"></script>
</body>
</html>
Javascript is :
Whenever this code is loaded :
var p1result = document.querySelector("#p1score");
var p2result = document.querySelector("#p2score");
var p1clicked = document.querySelector("#p1clicked");
function increment_score (player_result) {
//var score = parseInt(player_result.innerText) + 1;
player_result.innerText = (parseInt(player_result.innerText) + 1).toString();
}
p1clicked.addEventListener("onclick", increment_score(p1result))
Whenever this code is loaded in a browser, the span showing the result for player 1 is showing one directly without clicking on player 1 button. i'm not sure what is wrong with the event listener im using.
The event is click instead of onclick
The event listener should be a reference to the function itself, not the result of a function call (which increments the score by 1)
Inside the function, you can access the button with this:
The code could look like this:
function increment_score() {
var player_result = this;
player_result.innerText = (parseInt(player_result.innerText) + 1).toString();
}
p1clicked.addEventListener('click', increment_score);
Use click event not onclick
You pass result of function not instead reference to function
If you need pass parameters to event handler - you can use bind:
p1clicked.addEventListener("click", increment_score.bind({result: p1result, inc: 1 }) )
p2clicked.addEventListener("click", increment_score.bind({result: p2result, inc: 2 }) )
function increment_score () {
var score = parseInt(this.result.innerText) + this.inc;
this.result.innerText = score;
}
[ https://jsfiddle.net/6vw8ay3x/ ]
You have a couple problems there. First, when calling the addEventListener function, you need to specify just "click", not "onclick". Secondly, when you pass the function to addEventListener, you just want it to be a reference to the function not an actual function call. The following changes will net you the result you are seeking.
function increment_score () {
p1result.innerText = (parseInt(p1result.innerText) + 1).toString();
}
p1clicked.addEventListener("click", increment_score);
But since you want to be able to use the same function for multiple players, then I would suggest adding the "onclick" handler to the HTML which will allow you to pass the element you want to increment. Then your HTML code would look like this:
<button id="p1clicked" onclick="increment_score_with_param(p1result);">Player one</button>
<button id="p2clicked" onclick="increment_score_with_param(p2result);">Player two</button>
and your javascript would be:
var p1result = document.querySelector("#p1score");
var p2result = document.querySelector("#p2score");
var p1clicked = document.querySelector("#p1clicked");
function increment_score_with_param (player_result) {
player_result.innerText = (parseInt(player_result.innerText) + 1).toString();
}
window.onload = function(){
var p1result = document.querySelector('#p1score');
var p2result = document.querySelector('#p2score');
var p1clicked = document.querySelector('#p1clicked');
p1clicked.addEventListener("click", function(e){
e.preventDefault();
p1result.innerText = (parseInt(p1result.innerText) + 1).toString();
});
}

how to make the game save the best score with if statement javascript?

I am building a simple game as practice that counts the number of taps pressed in 3 seconds i have done everything apart from making it able to save the record score and if there is no record score then to show the old record.
<!DOCTYPE html>
<html>
<head>
<script type="text/javascript" src="javascript1.js"></script>
<link type="text/css" rel="stylesheet" href="firstcss.css">
</head>
</head>
<body>
<div id="div1">
<button onclick="myFunction()" id="something">GO
</button>
</div>
<div id="div2">
<p id="paragraph">0</p>
</div>
<p id="don"></p>
<p id="record"></p>
<p id="add"></p>
<script>
var cool = 1;
var red = 0;
function myFunction() {
document.getElementById("something").innerHTML = "Keep Tapping";
document.getElementById("paragraph").innerHTML = cool;
cool++;
var parent = document.getElementById("div1");
setTimeout(function() {
var ooo = cool - 1;
document.getElementById("don").innerHTML = ooo;
var parent = document.getElementById("div1");
var child = document.getElementById("something");
parent.removeChild(child);
var parent1 = document.getElementById("div2");
var child1 = document.getElementById("paragraph");
parent1.removeChild(child1);
if (cool - 1 > red) {
var red = cool - 1;
document.getElementById("record").innerHTML = red;
} else {
document.getElementById("record").innerHTML = red;
document.getElementById("add").innerHTML = red;
}
}, 3000);
}
</script>
</body>
</html>
I am using the if statement at the end but want to know how you would save the high score or if there isnt one to say the old high score. thanks it would be really helpful.
Check out the following resources on local storage:
http://diveintohtml5.info/storage.html
https://developer.mozilla.org/en-US/docs/Web/Guide/API/DOM/Storage
Essentially you can do (taken from the Dive int HTML 5 link):
var foo = localStorage.getItem("bar");
// ...
localStorage.setItem("bar", foo);

Categories