The idea is that I would like to add a text box in each div, that I have created dynamically.
HTML
<!DOCTYPE html>
<html>
<head>
<title>trial </title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<!--bootstrap setup-->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.16.0/umd/popper.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.min.js"></script>
<script src="trial.js"></script>
</head>
<div>
<p> Title</p>
</div>
<div>
<button class = "btn_add">Add </button>
</div>
<!-- level container-->
<div id = "container">
</div>
<!--stuff container -->
<div id="random_container">
</div>
</body>
</html>
JS
$(document).ready(function () {
var i = 1;
$(document).on('click', '.btn_add', () => {
let newElement = document.createElement('div');
newElement.setAttribute("id", "level_" + i);
newElement.setAttribute("class", "panel");
$('#container').append(`<div id="title">\
Level ` + i +`
</div> \
<div>\
<button id =btnadd_`+ i +` class="btn_addStuff"> Add Stuff </button>
</div>`);
$('#container').append(newElement);
i = i + 1;
});
$(document).on('click', '.btn_addStuff', () => {
/**let element = document.getElementById(div = "level_"+i);
element.append(`<div id="card"> \
<textarea placeholder="Title" type="text" maxlength="10" rows="1">Stuff</textarea> \
</div>`);
$('random_container').append(element); */
$('#random_container').append(`<div id="card"> \
<textarea placeholder="Title" type="text" maxlength="10" rows="1">Stuff</textarea> \
</div>`
);
});
});
My idea is that if I click the button add, I should have a div where there is level 1 and the button add stuff. Which it works.
For example, if I click 3 times, the button add, I should have three div, which each contains a button "add stuff" and the name level. What I would like to do, is if I click the button add stuff, it should appear a text box. The problem that I am having with my code, is that I am not able to have the text box in the right position. If I am in the level one and I click 2 times the button add stuff, I should get two text boxes in the level one, and if I decide to click 3 times on the level 2 to get 3 boxes, I should get 3 text boxes.
Instead, what happens, it's that I am having the text boxes only in one level.
What I thought is to try to get the id in the addstuff button and then try to append the code and then add everything in the random_container, but I can't get an element that has created dynamically?
Hope the question is clear.
If i understood correctly then You should remove the random_container and add the textareas below the inputs
<!DOCTYPE html>
<html>
<head>
<title>trial </title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<!--bootstrap setup-->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.16.0/umd/popper.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.min.js"></script>
<script src="trial.js"></script>
</head>
<body>
<div>
<p> Title</p>
</div>
<div>
<button class = "btn_add">Add </button>
</div>
<!-- level container-->
<div id = "container">
</div>
</body>
<script>
function addStaff(btn) {
var parent = $(btn).parent()
console.log(parent)
parent.append(`
<div id="card">
<textarea placeholder="Title" type="text" maxlength="10" rows="1">Stuff</textarea>
</div>
`)
}
$(document).ready(function () {
var i = 1;
$(document).on('click', '.btn_add', () => {
let newElement = document.createElement('div');
newElement.setAttribute("id", "level_" + i);
newElement.setAttribute("class", "panel");
$('#container').append(`
<div id="title">
Level ${i}
</div>
<div id="add_staff-${i}">
<button id="btnadd_${i}" onclick="addStaff(this)"> Add Stuff </button>
</div>
`);
$('#container').append(newElement);
i = i + 1;
});
});
</script>
</html>
Seeing as you're using jQuery, you're life will be a lot easier using jQuery to create the new elements:
var i = 1;
$(".btn_add").on('click', () => {
// Create Main Div
var mainDiv = $("<div />").prop("id", "level_" + i).addClass("panel");
// Create Title Div
var divTitle = $("<div />").prop("id", "title_" + i).html("Level " + i);
// Create Button to add cards inside this div
var divButton = $("<button />")
.prop("id", "btnAdd" + i)
.html("Add Stuff")
.on('click', () => {
// Get number of cards already in this div so we can generate unique id
var cardCount = $("#level_" + i).find(".card").length;
// create the Card
var card = $("<div />").prop("id", "card_" + cardCount + 1).addClass("card").html("I am a card");
// Put the card in this div
$("#level_" + i).append(card);
}));
// Put it together
mainDiv.append(divTitle).append(divButton);
// Put it in the container
$("#container").append(mainDiv);
// Increment the counter
i++;
});
Note: Your code will try to create elements with the same id in places. Can't do that.
Related
I am making a note-taking app and I want 2 text areas to when you type in one the other changes to
what you are doing in one. I want so when I change the title of the page it will change in other places on the page. I'll provide my current code what my page looks like (I want the change to be with my Unititled and an area next to the dropdown arrow) and what I want it to do, I've tried change and input events and I can't seem to figure it out.[My Current Site][1]
What I Want - https://share.vidyard.com/watch/Wj6uTmEiB9LR8iiZy7sVf9
[1]: https://i.stack.imgur.com/3vzEB.png
<!DOCTYPE HTML>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Study App</title>
<link rel="stylesheet" href="study.css" />
<link href="https://unpkg.com/boxicons#2.0.7/css/boxicons.min.css" />
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-
awesome/5.15.1/css/all.min.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.5.1/jquery.min.js" charset="utf-
8"></script>
</head>
<body>
<script src="study.js"></script>
<div class="dropdown">
<nav><label for="touch"><span>Settings</span></label>
<input type="checkbox" id="touch" />
<ul class="slide">
<li><a>
<div class="dark"><button onclick="myFunction()">
<input class="toggle" type="checkbox" /></button></div>
</a></li>
<li></li>
</ul>
</nav>
</div>
</div>
<div class="arrowdown">
<input type="checkbox" id="myCheckbox" onchange="rotateElem()" checked><i class="fas fa-angle-
right dropdown"></i></button>
<div class="pages">
Add Page
</div>
</div>
</div>
<script type="text/javascript">
var checkBox = document.getElementById("myCheckbox");
function rotateElem() {
if (checkBox.checked == false) {
document.querySelector('.fas.fa-angle-right.dropdown').style.transform = 'rotate(90deg)';
} else {
document.querySelector('.fas.fa-angle-right.dropdown').style.transform = 'rotate(0deg)';
}
}
</script>
<div class="tabs"></div>
<div class="sidebar">
<div class="sidebar-top">
<h1><span class="study">Study</span><span class="app">App</span></h1>
</div>
<div class="title">
<textarea id="shortInput" spellcheck="true" placeholder="Untitled" cols="30" rows="1">
</textarea>
</div>
<div class="textbox">
<textarea id="longInput" spellcheck="true" placeholder="Start typing..." cols="30" rows="10"></textarea>
</div>
<script type="text/javascript">
$('.pages').hide();
$(document).ready(function() {
$('input').click(function() {
$('.pages').slideToggle();
});
});
</script>
<script src="study.js"></script>
</body>
</html>
One possible approach would be to store the synchronised value in a variable, and add event listeners to each element for any changes. Then update the value of each element with the new value when the change occurs.
// Store the synchronised content
let value = ''
// Add change listeners to each element
const elements = document.querySelectorAll('.synced')
for (let i = 0; i < elements.length; i++) {
// Different browsers will work better with different events
// but there's no problem with listening for multiple
elements[i].addEventListener('change', handleChange)
elements[i].addEventListener('input', handleChange)
elements[i].addEventListener('keyup', handleChange)
}
// When a change occurs, set the value of all the synchronised elements
function handleChange(e) {
value = e.target.value
for (let i = 0; i < elements.length; i++) {
elements[i].value = value
}
}
<textarea class="synced"></textarea>
<textarea class="synced"></textarea>
<textarea class="synced"></textarea>
jQuery version:
// Store the synchronised content
let value = ''
// Get all the of the relevant elements
const elements = $('.synced')
// Different browsers will work better with different events
// but there's no problem with listening for multiple
elements.on('change input keyup', function() {
value = $(this).val()
elements.val(value)
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<textarea class="synced"></textarea>
<textarea class="synced"></textarea>
<textarea class="synced"></textarea>
So I'm trying to create my own To Do list just to learn javascript and I'm stuck.
I've managed to add a new div with the input that the user writes, but there's no design.
<div class="isDo"> // HTML code
<p id="newTask">Task 1</p>
<hr>
</div>
function addTask() { // JavaScript Code
var div = document.createElement("div");
var taskAdd = document.getElementById("taskAdd").value;
div.innerHTML = taskAdd;
document.getElementsByClassName("isDo")[0].appendChild(div);
}
When I used append paragraph instead of div it the design works, but I want to ad an <hr> tag for each input value.
What way can I add an entire div with paragraph and hr tag?
This should do the trick :)
`
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
<div class="isDo">
<p id="newTask">Task 1</p>
<hr>
</div>
<button id="btn" >add a tag</button>
<script>
function addTask() { // JavaScript Code
var div = document.createElement("div");
var taskAdd = document.getElementById("newTask").innerHTML;
//change the id of the el because taskAdd doesn't point to an element
div.innerHTML = `<p>${taskAdd}</p><hr>`;
//this is the part where you add the text in taskAdd and the hr tag
document.getElementsByClassName("isDo")[0].appendChild(div);
}
var btn = document.getElementById("btn")
.addEventListener("click", addTask);
</script>
</body>
</html>
`
Try this below :
<!DOCTYPE html>
<html>
<title>Test Code</title>
<head>
<script>
function addTask() {
var div = document.createElement("div");
var taskAdd = document.getElementById("taskAdd").value;
div.innerHTML = taskAdd + "<hr>";
document.getElementsByClassName("isDo")[0].appendChild(div);
}
</script>
</head>
<body>
<input id="taskAdd">
<button onclick="addTask()">Add</button>
<div class="isDo">
<p id="newTask">Task 1</p>
<hr>
</div>
</body>
</html>
I really struggling with this.
I need to basically make it so whatever is written in a newly created textbox is stored in local storage.
// TODO: Q1(c)(iii)
// Make an event listener to save text when it changes:
// ...get the textarea element's current value
// ...make a text item using the value
// ...store the item in local storage using the given key
// Connect the event listener to the textarea element
var item, data, key;
var textareaElement = document.createElement("TEXTAREA");
textareaElement.addEventListener("change", function(event) {
var myText = document.getElementById("textareaElement").value;
localStorage.setItem("text", myText);
item = makeItem ("text", myText);
});
-- HTML --
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>My Erehwon Diary ds22368</title>
<meta name="author" content="Stephen Rice" />
<!-- Set viewport to ensure this page scales correctly on mobile devices -->
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="stylesheet" href="tma03.css" />
<!-- Set demo data -->
<script src="tma03-demo.js"></script>
<!-- Start TMA03 application -->
<script src="tma03.js"></script>
</head>
<body>
<h1>My Erehwon Diary ds22368</h1>
<main>
<section id="text" class="button">
<button type="button">Add entry</button>
</section>
<section id="image" class="button">
<button type="button">Add photo</button>
<input type="file" accept="image/*" />
</section>
</main>
</body>
</html>
The questions for each line are the comments above, and below them is what I've tried so far.
var item, data, key;
var textareaElement = document.createElement("TEXTAREA");
document.body.appendChild(textareaElement); //Add the element to the document
textareaElement.addEventListener("change", function(event) {
var mytext = textareaElement.value; //You already have the element as a variable
localStorage.setItem("text", myText);
item = makeItem("text", myText);
});
function makeItem() { //Don't forget to define makeItem
//code
}
Create an input like this in your HTML
<textarea id=‘textarea’ onchange=‘save()’ />
In JS:
const textarea = document.querySelector(‘#textarea’)
function save() {
localStorage.setItem("text", textarea.value);
}
I keep having the same issue again and again : When I add a task, it gets added to the localStorage correctly. But once I have multiple tasks and I click complete on a random one, sometimes it happens that the LocalStorage removes the task before it or after it. I can't figure out a way how to let it work.
let addBtn = document.getElementById("addButton");
let textInput = document.getElementById("textInput");
let mainList = document.getElementById("mainList");
let storage = JSON.parse(localStorage.getItem("toDos")) || [];
if (storage.length != 0){
for (let i=0; i<storage.length;i++){
addTask(mainList, storage[i]);
};
};
function addTask(list,task){
var newTask = document.createElement("li");
newTask.textContent=task
newTask.className="task d-flex justify-content-between list-group-item bg-primary mt-2";
addCompleteBtn(newTask);
list.appendChild(newTask);
}
function addCompleteBtn (newTask){
let completeBtn = document.createElement("button");
completeBtn.className="btn btn-success completeBtn";
completeBtn.textContent="Completed";
newTask.appendChild(completeBtn);
};
addBtn.addEventListener("click", ()=>{
if(textInput.value === ""){
alert("Error: The field is either empty or you entered more than 100 characters!");
}else{
storage.push(textInput.value);
addTask(mainList, textInput.value);
textInput.value="";
localStorage.setItem("toDos",JSON.stringify(storage));
};
});
mainList.addEventListener("click",(evt)=>{
if (evt.target.className==="btn btn-success completeBtn") {
let listItem = evt.target.parentNode;
let mainUl = listItem.parentNode;
let toBeRemoved = listItem.textContent;
storage.splice(storage.indexOf(toBeRemoved),1);
mainUl.removeChild(listItem);
localStorage.setItem("toDos",JSON.stringify(storage));
};
});
<!doctype html>
<html lang="en">
<head>
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<!-- Bootstrap CSS -->
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous">
<link rel="stylesheet" href="style.css">
<title>To-do-list App</title>
</head>
<body>
<div class="jumbotron bg-info">
<div class="container">
<h1 class="display-4 text-center">Task List</h1>
<p class="lead text-center">Click on the Add button to add a task</p>
</div>
</div>
<div class="container">
<div class="firstInput input-group mb-5">
<div class="input-group-prepend">
<button class="btn btn-primary" type="button" id="addButton">Add Task</button>
</div>
<input type="text" title='Enter a Task' class="form-control" id="textInput" maxlength="200">
</div>
</div>
<ul class='tasksList container' id="mainList">
</ul>
<script src="script.js"></script>
</body>
</html>
Shows all the values in the LocalStorage
Once task 2 is removed, task 3 is removed from the Storage instead
this is the specific part that causes me issues :
mainList.addEventListener("click",(evt)=>{
if (evt.target.className==="btn btn-success completeBtn") {
let listItem = evt.target.parentNode;
let mainUl = listItem.parentNode;
let toBeRemoved = listItem.textContent;
/* This is the part of code causing me issues
storage.splice(storage.indexOf(toBeRemoved),1);
*/
mainUl.removeChild(listItem);
localStorage.setItem("toDos",JSON.stringify(storage));
};
});
The problem is here let toBeRemoved = listItem.textContent;,this will return the text content of all elements inside that li. So if you add a task named 'Task 1', when you press Completed the value of toBeRemoved will be Task 1Completed since this will return the text of the button as well since your button is a child of the li.
So change let toBeRemoved = listItem.textContent; to let toBeRemoved = listItem.childNodes[0].nodeValue; and you should be fine, this will get the text of the li only.
I really tried everything, almost every function in JS. But I cannot remove the list item from the to-do list once it is added. I have tried adding event listeners, onclick=" " etc but nothing works. Can someone please look at my code and tell me what I am doing wrong. Thank You, any help is much appreciated.
HTML:
<!DOCTYPE html>
<html lang="en">
<head>
<script
src="https://code.jquery.com/jquery-3.3.1.js"
integrity="sha256-2Kok7MbOyxpgUVvAk/HJ2jigOSYS2auK4Pfzbm7uH60="
crossorigin="anonymous"></script>
<script src="script.js"></script>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet href="style.css">
<link rel="stylesheet" href="style.css">
<link href="https://fonts.googleapis.com/css?family=Roboto" rel="stylesheet">
<meta charset="UTF-8">
<title>To-Do-List</title>
</head>
<body>
<div class="container">
<div id="header">
<h1>My To Do List</h1>
</div>
<form autocomplete="off">
<input type="text" id="task" placeholder="Title...">
</form>
<button id="addTask">Add</button>
</div>
<br><br>
<div id="tasks">
<ul id="myUL">
</ul>
</div>
</div>
</div>
<script>
var list = document.getElementById('myUL');
list.addEventListener("click", boxChecked);
function boxChecked(event){
const element = event.target;
if(element.type === "close"){
delete element;
}
}
</script>
</body>
</html>
JS:
$(document).ready(function(){
document.getElementById('addTask').addEventListener("click", function(){
var task = document.getElementById('task').value;
if(task == ""){
alert("You Must Enter A Value!");
}else{
document.getElementById('myUL').innerHTML += '<li>' + task + '</li>' + '<button class="close" >✗</button>' + '<br><br>' + '<button class="check" >✓</button>' + '<br><br>';
}
var button = document.querySelectorAll('.close');
for(var i = 0; i < button.length;i++){
button[i].addEventListener("click", function(){
this.parentNode.removeChild(this.previousSibling);
this.parentNode.removeChild(this);
});
}
var check = document.querySelectorAll('.check');
for(var i = 0; i < check.length;i++){
check[i].addEventListener("click", function(){
this.parentNode.style.textDecoration = "line-through";
});
}
});
});
Don't try to concatenate innerHTML strings when you have listeners attached to elements inside, else the listeners will be lost. Instead, append elements properly with appendChild.
delete element won't actually do anything, because element is a variable, not a property of an object - try using .remove() instead, to remove the li (and put the button inside the li so that the HTML is valid).
var list = document.getElementById('myUL');
list.addEventListener("click", boxChecked);
function boxChecked(event) {
const element = event.target;
if (element.className === "close") {
element.parentElement.remove();
}
}
document.getElementById('addTask').addEventListener("click", function() {
var task = document.getElementById('task').value;
if (task === "") return alert("You Must Enter A Value!");
const li = list.appendChild(document.createElement('li'));
li.textContent = task;
const button = li.appendChild(document.createElement('button'));
button.className = 'close';
button.textContent = '✗';
});
.close {
position: absolute;
left: 150px;
}
<div class="container">
<div id="header">
<h1>My To Do List</h1>
</div>
<form autocomplete="off">
<input type="text" id="task" placeholder="Title...">
</form>
<button id="addTask">Add</button>
</div>
<br><br>
<div id="tasks">
<ul id="myUL">
</ul>
</div>
Your .querySelectorAll() simply needs to target .close rather than close. In addition to this, you'll probably want to target the close button's parent (the item itself), with .parentNode. Note that you probably don't want to hide it, but rather actually simply remove both the <li> and the close icon, so that you can add more items after removal of the item(s). This can be done with:
this.parentNode.removeChild(this.previousSibling);
this.parentNode.removeChild(this);
And can be seen working in the following:
var list = document.getElementById('myUL');
list.addEventListener("click", boxChecked);
function boxChecked(event) {
const element = event.target;
if (element.type === "close") {
delete element;
}
}
$(document).ready(function() {
document.getElementById('addTask').addEventListener("click", function() {
var task = document.getElementById('task').value;
if (task == "") {
alert("You Must Enter A Value!");
} else {
document.getElementById('myUL').innerHTML += '<li>' + task + '</li>' + '<button class="close" >✗</button>' + '<br><br>';
}
var button = document.querySelectorAll('.close');
for (var i = 0; i < button.length; i++) {
button[i].addEventListener("click", function() {
this.parentNode.removeChild(this.previousSibling);
this.parentNode.removeChild(this);
});
}
});
});
<!DOCTYPE html>
<html lang="en">
<head>
<script src="https://code.jquery.com/jquery-3.3.1.js" integrity="sha256-2Kok7MbOyxpgUVvAk/HJ2jigOSYS2auK4Pfzbm7uH60=" crossorigin="anonymous"></script>
<script src="script.js"></script>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="style.css">
<link rel="stylesheet" href="style.css">
<link href="https://fonts.googleapis.com/css?family=Roboto" rel="stylesheet">
<meta charset="UTF-8">
<title>To-Do-List</title>
</head>
<body>
<div class="container">
<div id="header">
<h1>My To Do List</h1>
</div>
<form autocomplete="off">
<input type="text" id="task" placeholder="Title...">
</form>
<button id="addTask">Add</button>
</div>
<br><br>
<div id="tasks">
<ul id="myUL">
</ul>
</div>
</body>
</html>
Also note that your stylesheet is missing a closing ", and you have two additional closing </div> that don't match anything in your above code.