I want to make a function to create a new box when I click 'add new box' button and after that, it will also able to delete the box when I click the particular delete button which is related with the box. How to make the function in javascript? Should I save in an array for every new element that it creates?
My code:
function addBox() {
var el = document.getElementById('target');
var clone = el.cloneNode(true);
var frame = document.getElementById('container');
var attr = document.createAttribute('val');
attr.value = 'demo';
el.setAttributeNode(attr);
frame.appendChild(clone);
}
<div id="container">
<div id="target" class="foo" val="demo">
<div class="content" style="width:100px;height:100px;background:orange;margin:1px" ></div>
</div>
</div>
<button onclick="addBox();">Add box</button>
<button onclick="deleteBox();">Delete box</button>
I wanted to be like this!
You need to target the button element using this as an argument on the deleteBox() function and then the parent of the button by using parentNode and then apply remove() method on it:
function addBox() {
var el = document.getElementById('target');
var clone = el.cloneNode(true);
var frame = document.getElementById('container');
var attr = document.createAttribute('val');
attr.value = 'demo';
el.setAttributeNode(attr);
frame.appendChild(clone);
}
function deleteBox(e){
e.parentNode.remove()
}
.content{
width: 100px;
height: 100px;
margin-bottom: 10px;
background: #F5A623;
display: inline-block;
vertical-align: middle;
}
<div id="container">
<div id="target" class="foo" val="demo">
<div class="content" style="width:100px;height:100px;background:orange;margin:1px"></div>
<button onclick="deleteBox(this);">Delete</button>
</div>
</div>
<button onclick="addBox();">Add box</button>
As a sidenote, I strongly recommend you to have unique ids on elements.
Try this,
<div id="container">
<div id="target" class="foo" val="demo">
<div class="content">aaa</div>
<button onclick="deleteBox(this);">Delete box</button>
</div>
</div>
<button onclick="addBox();">Add box</button>
function addBox() {
var el = document.getElementById('target');
var clone = el.cloneNode(true);
var frame = document.getElementById('container');
var attr = document.createAttribute('val');
attr.value = 'demo';
el.setAttributeNode(attr);
frame.appendChild(clone);
}
function deleteBox(obj){
obj.parentElement.remove();
}
JQuery:
function deleteBox(){
$( "#target" ).remove();
}
Javascript:
function deleteBox(){
document.getElementById('target').remove()
}
This is alternative example, You can try in your code :)
var sentenceIndex = 1;
function addSentence() {
var n = sentenceIndex;
var html = '<div class="form-item-wrap" id="sentencebox' + n + '">'+
'<div class="form-item">'+
'<input class="form-control" type="text" id="sentence'+n+'" name="sentence[' + n + ']">'+
'</div>'+
'<div class="course-region-tool">'+
'<a href="javascript:void(0);" onclick="removeSentence('+n+');" class="delete" title="delete">'+
'<i class="icon md-recycle"></i></a></div></div>';
$("#addSentenceDiv").append(html);
sentenceIndex = sentenceIndex + 1;
}
function removeSentence(id) {
console.log(id);
$("#sentencebox"+id).remove();
}
Related
How do I move the button from the div with id of two to the div with id of one when I click the button?
<div id="one">
</div>
<div id="two">
<button onclick="moveMe"></button>
</div>
function moveMe() {
// ??
}
We can do this using removeChild and appendChild js features. Provided an example below with working code.
const one = document.getElementById("one");
const two = document.getElementById("two");
const allButtons = document.getElementsByTagName("button");
for(let i = 0; i < allButtons.length; i++) {
const btn = allButtons[i];
btn.addEventListener("click", function(e) {
const el = e.currentTarget;
const newParent = el.parentNode.id == "one" ? two : one;
el.parentNode.removeChild(el);
newParent.appendChild(el)
});
}
.section {
height: 100px;
width: 150px;
padding: 4px;
margin: 5px;
float: left;
}
#one {
background: #CCC;
}
#two {
background: #eee;
}
button {
margin: 2px;
padding: 4px;
}
<h3>Toggle button between container on click</h3>
<div>
<div class="section" id="one"></div>
<div class="section" id="two"> <button>Move me 1</button> <button>Move me 2</button></div>
</div>
function moveMe() {
const divTwo = document.getElementById("two")
const divOne = document.getElementById("one")
const newButton = document.createElement("button")
newButton.innerText = "Click me"
divOne.appendChild(newButton)
divTwo.children[1].remove()
}
<div id="one">
<p>
div one
</p>
</div>
<div id="two">
<p>
div two
</p>
<button onclick="moveMe()">Click me</button>
</div>
You can try this:
// select the elements
const button = document.querySelector('button');
const firstDiv = document.getElementById('one');
// add eventListener
button.addEventListener('click', moveButton);
// move the button
function moveButton() {
firstDiv.append(button);
}
<div id="one">
</div>
<div id="two">
<button id="btn" onclick="moveMe">MoveMe</button>
</div>
function moveMe() {
var divOne = document.querySelector("#one");
var btn = document.querySelector("#btn");
divOne.appendChild(btn);
}
You can use code below to move the element.
There's some changes that I made on your code,
you can use version 1 or version 2
the changes on first version is i add "id" attribute on the element so we don't resort to use the tag only as selector, of course you can also use #two>button to make it more precise
the changes on second version is i add a parameter to your function this time it will handle the current element using "this" keyword when calling the function
function moveMe(){
// one.appendChild(document.querySelector("button"));
one.appendChild(move);
}
function moveMeV2(element){
one.appendChild(element);
}
<div id="one">
<span>one</span>
</div>
<div id="two">
<span>two</span>
<button id="move" onclick="moveMe()">Move Me</button>
<button onclick="moveMeV2(this)">Move Me V2</button>
</div>
In my web-page I have various buttons (in the class .addbutton). When the first of these is clicked, a <div> appears with a drop-down, from which the user can select any of 2 options (#p1, `#p2), which vary depending on which button was clicked.
When each of these options is clicked, I want it to appear in the <div> that corresponds with the initial .addbutton that was clicked. (e.g if the first .addbutton is clicked (#bradd) I want the options selected in the first div (#bdiv))I managed to do this so that they always appear in the #bdiv, no matter what .addbutton was clicked, but I can't work out how to make each appear in the corresponding one.
JS to set the innerHTML of the 2 options
document.getElementById("bradd").onclick = function() {
document.getElementById("p1").innerHTML = "Cereal"
document.getElementById("p2").innerHTML = "Juice"
}
document.getElementById("mmadd").onclick = function() {
document.getElementById("p1").innerHTML = "2x small fruit"
document.getElementById("p2").innerHTML = "Big fruit"
}
JS to change the innerHTML of the first div (#bdiv)
document.getElementById("p1").onclick = function() {
var newItem = document.createElement("div")
newItem.innerHTML = document.getElementById("p1").innerHTML document.getElementById("bdiv").appendChild(newItem)
}
document.getElementById("p2").onclick = function() {
var newItem = document.createElement("div")
newItem.innerHTML = document.getElementById("p2").innerHTML
document.getElementById("bdiv").appendChild(newItem)
}
My HTML:
<h1>Meal Plan Customizer</h1>
<div id="list">
<input type="checkbox">
<p>Breakfast:</p>
<button class="addbutton" id="bradd">+</button>
<div id="bdiv"></div>
<br>
<input type="checkbox">
<p>Mid-Morning:</p>
<button class="addbutton" id="mmadd">+</button>
<div id="mdiv"></div>
<br>
<input type="checkbox">
<div id="dropdownList">
<p id="p1">Option1</p><br><br>
<p id="p2">Option2</p><br><br>
</div>
</div>
</div>
Your code should work.
Please check this:
https://jsfiddle.net/oliverdev/3wsfgov1/
If your code is not working, it is because Javascript code is loaded before loading the HTML.
You can modify the Javascript code like this:
window.onload = function(e){
document.getElementById("bradd").onclick = function() {
document.getElementById("p1").innerHTML = "Cereal"
document.getElementById("p2").innerHTML = "Juice"
}
document.getElementById("mmadd").onclick = function() {
document.getElementById("p1").innerHTML = "2x small fruit"
document.getElementById("p2").innerHTML = "Big fruit"
}
}
It will work for you
You are making this far more complicated and repetitive than necessary.
By storing your data in a structured object and using classes for the content elements you can make generic event listeners for all of this
Following is by no means complete but will give you a good idea how to approach something like this
var data = {
bradd: {
p1: "Cereal",
p2: "Juice"
},
mmadd: {
p1: "2x small fruit",
p2: "Big fruit"
}
}
var selectedButton = null;
var opts = document.querySelectorAll('#dropdownList p');
for (let p of opts) {
p.addEventListener('click', updateContent)
}
// generic event handler for all the options
function updateContent() {
const content = selectedButton.closest('.item').querySelector('.content')
content.innerHTML = this.innerHTML
togglePopup()
}
document.querySelector('#xbutton').addEventListener('click', togglePopup)
// generic event handler for all buttons
function addButtonClicked() {
selectedButton = this;// store selected for use when option selected
var wantedData = data[selectedButton.id];
for (let p of opts) {
p.innerHTML = wantedData[p.id]
}
togglePopup();
}
for (let btn of document.getElementsByClassName("addbutton")) {
btn.addEventListener("click", addButtonClicked)
}
function togglePopup() {
var popStyle = document.getElementById("addPopUp").style;
popStyle.display = popStyle.display === "block" ? 'none' : 'block'
}
#addPopUp {
display: none
}
<h1>Meal Plan Customizer</h1>
<div id="list">
<div class="item">
<p>Breakfast:</p>
<button class="addbutton" id="bradd">+</button>
<div class="content"></div>
</div>
<div class="item">
<p>Mid-Morning:</p>
<button class="addbutton" id="mmadd">+</button>
<div class="content"></div>
</div>
</div>
<div id="addPopUp">
<h3 id="h3">Select what you would like to add:</h3>
<span id="xbutton"><strong>×</strong></span>
<div class="dropdown">
<div id="dropdownList">
<p id="p1">Option1</p>
<p id="p2">Option2</p>
<!-- <p id="p3">Option3</p><br><br>
<p id="p4">Option4</p>-->
</div>
</div>
</div>
I'm trying to select visible children after appending them into a temp div.
But I got undefined. I've prepared a pen here: codepen
function createTemp() {
var innerObj = $('.main');
var el = $('<div class="doc-temp" style="display: none;"><div class="temp2">' + innerObj.html() + '</div></div>');
$('body').append(el);
var visible = el.children(':visible');
return visible;
}
console.log(createTemp().html());
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="main">
<span>Well</span> Hello
<span>Three</span> Hi Hello
<span style="display: none;">Four</span>
<span>Five</span> See you
</div>
If your element is hidden it will NOT have ANY :visible descendants!
Also you need the HTML of main
If you want the children that WOULD be visible if the PARENT was, you can do this:
function createTemp() {
var innerObj = $('.main').html();
var el = $('<div class="doc-temp"><div class="temp2"></div></div>');
$("body").append(el);
$(".temp2").append(innerObj);
var children = $(".temp2")[0].childNodes;
return [...children].map(el => {
if (el.getAttribute) {
return el.getAttribute("style") === "display: none;" ? null : el.outerHTML
}
return el === null ? null : el.textContent;
})
}
$("#ta").val(createTemp().join(""));
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="main">
<span>Well</span> Hello
<span>Three</span> Hi Hello
<span style="display: none;">Four</span>
<span>Five</span> See you
</div>
<textarea rows="100" cols="100" id="ta"></textarea>
Modify your function to below:
function createTemp(){
var innerObj = $('.main');
var el = '<div class="doc-temp" style="display: none;"><div class="temp2">' + innerObj.html() + '</div></div>';
$('body').append(el);
var visible = $('.main').find(':visible');
return visible;
}
After this change, you can iterate through the visible array. Use $.each for this iteration process.
I am trying to add different classes to a div based on what is clicked, which I've managed to do, but need to remove the previously clicked/selected class and replace with the clicked one, Can't seem to get the remove part right. Most of the solutions I've come across are either toggles or adding and removing between two classes, but not 3 or more.
Thanks
This is what I have tried so far and the add part works as expected but when I click a different button it does not remove the previous clicked one
The HTML
<button id="btn-1" data-width="w-1/3">Mobile</button>
<button id="btn-2" data-width="w-2/3">Tablet</button>
<button id="btn-3" data-width="w-full">Desktop</button>
<div class="frame">
Some Content
</div>
The Javascript
let setMobile = document.querySelector('#btn-1');
let setTablet = document.querySelector('#btn-2');
let setDesktop = document.querySelector('#btn-3');
let btns = [setMobile, setTablet, setDesktop];
function getBtnId(btn) {
btn.addEventListener('click', function() {
let frame = document.querySelector('.frame')
frame.classList.add(this.dataset.width)
if(frame.classList.contains(btns)){
frame.classList.remove(this.dataset.width)
}
console.log(this.dataset.width);
});
}
btns.forEach(getBtnId);
Basically, what I am trying to do is a responsive frame which will adjust its width depending on what is clicked.
You can store the current class in a variable and use the remove() to remove the previous class on each click.
let setMobile = document.querySelector('#btn-1');
let setTablet = document.querySelector('#btn-2');
let setDesktop = document.querySelector('#btn-3');
let btns = [setMobile, setTablet, setDesktop];
var currentClass;
function getBtnId(btn) {
btn.addEventListener('click', function() {
let frame = document.querySelector('.frame')
if (currentClass) {
frame.classList.remove(currentClass);
}
currentClass = this.dataset.width;
frame.classList.add(currentClass);
console.log(this.dataset.width);
});
}
btns.forEach(getBtnId);
<button id="btn-1" data-width="w-1/3">Mobile</button>
<button id="btn-2" data-width="w-2/3">Tablet</button>
<button id="btn-3" data-width="w-full">Desktop</button>
<div class="frame">
Some Content
</div>
Here's a generalized version to work with multiple elements. I've wrapped each frame and buttons in a section element. Then I've bound the event listeners to the sections and used event bubbling / event delegation to perform the switch. I've also used a data attribute on the target frame to hold the current state.
function setWidthClass(event) {
var newWidth = event.target.dataset.width;
//This identifies a button click with our dataset
if (newWidth) {
//get the target div
var target = this.querySelector(".frame");
//if the target has a class set remove it
if (target.dataset.width) {
target.classList.remove(target.dataset.width);
}
//Add the new class
target.classList.add(newWidth);
//Update the data on the target element
target.dataset.width = newWidth;
}
}
//Add the event listener
var sections = document.querySelectorAll(".varyWidth");
for (var i = 0; i < sections.length; i++) {
sections[i].addEventListener("click", setWidthClass);
}
.w-third {
color: red;
}
.w-half {
color: blue;
}
.w-full {
color: green;
}
<section class="varyWidth">
<button data-width="w-third">Mobile</button>
<button data-width="w-half">Tablet</button>
<button data-width="w-full">Desktop</button>
<div class="frame">
Some Content
</div>
</section>
<section class="varyWidth">
<button data-width="w-third">Mobile</button>
<button data-width="w-half">Tablet</button>
<button data-width="w-full">Desktop</button>
<div class="frame">
Some Content
</div>
</section>
<section class="varyWidth">
<button data-width="w-third">Mobile</button>
<button data-width="w-half">Tablet</button>
<button data-width="w-full">Desktop</button>
<div class="frame">
Some Content
</div>
</section>
Rather than track the current class, you can also just reset it:
let setMobile = document.querySelector('#btn-1');
let setTablet = document.querySelector('#btn-2');
let setDesktop = document.querySelector('#btn-3');
let btns = [setMobile, setTablet, setDesktop];
function getBtnId(btn) {
btn.addEventListener('click', function() {
let frame = document.querySelector('.frame')
// reset the classList
frame.classList = ["frame"];
frame.classList.add(this.dataset.width)
console.log(this.dataset.width);
});
}
btns.forEach(getBtnId);
<button id="btn-1" data-width="w-1/3">Mobile</button>
<button id="btn-2" data-width="w-2/3">Tablet</button>
<button id="btn-3" data-width="w-full">Desktop</button>
<div class="frame">
Some Content
</div>
I'm practicing with javascript. I built a grocery list in which I would like to add and remove items. Adding elements works fine by typing a name in a input form and pushing the send button. I'd like to remove the element that I just created by clicking on it but I get this error instead:
"Uncaught TypeError: Cannot read property 'removeChild' of undefined at HTMLDocument.removeItem"
here the code:
HTML:-
<div id="paper">
<h3 id="title">Groceries list:</h3>
<ul id="list">
<li></li>
</ul>
</div>
<p class="grocery">
<input type="text" name="grocery" placeholder="ex. Apple" id="blank" />
<label for="grocery">Grocery Name</label>
</p>
<p class="submit">
<input type="submit" value="SEND" id="btn" />
</p>
<script type="text/javascript" src="js/script.js"></script>
CSS:-
#paper {
width: 300px;
height: auto;
margin: 20px auto;
clear: both;
background-color: orange;
}
.grocery, .submit{
text-align: center;
margin: 20px;
}
Javascript:-
var elList = document.getElementById("list");
var elButton = document.getElementById("btn");
function addItem(e) {
var elElement = document.createElement("li");
var whatever = el.value;
var elText = document.createTextNode(whatever);
elElement.appendChild(elText);
elList.appendChild(elElement);
}
function removeItem(e) {
var elElement = document.getElementsByTagName("li");
var elContainer = elElement.parentNode;
elContainer.removeChild(elElement);
}
var el = document.getElementById("blank");
elButton.addEventListener("click", addItem, false);
if ("DOMNodeInserted") {
document.addEventListener("click", removeItem, false);
}
How could I get through this?
Thank you guys for your help
if ("DOMNodeInserted") {
document.addEventListener("click", removeItem, false);
} is wrong. you need to attach this event handler to each list you create.
you can do that in addItem() using elElement.addEventListener("click", removeItem, false);, then in removeItem(e) just use e to get current element using e.currentTarget and remove it.
This seems to work:
var elList = document.getElementById("list");
var elButton = document.getElementById("btn");
function addItem(e) {
var elElement = document.createElement("li");
var whatever = el.value;
var elText = document.createTextNode(whatever);
elElement.appendChild(elText);
elList.appendChild(elElement);
elElement.addEventListener("click", removeItem, false);
}
function removeItem(e) {
var elElement = e.currentTarget;
var elContainer = elElement.parentNode;
elContainer.removeChild(elElement);
}
var el = document.getElementById("blank");
elButton.addEventListener("click", addItem, false);
#paper {
width: 300px;
height: auto;
margin: 20px auto;
clear: both;
background-color: orange;
}
.grocery, .submit{
text-align: center;
margin: 20px;
}
<div id="paper">
<h3 id="title">Groceries list:</h3>
<ul id="list">
<li></li>
</ul>
</div>
<p class="grocery">
<input type="text" name="grocery" placeholder="ex. Apple" id="blank" />
<label for="grocery">Grocery Name</label>
</p>
<p class="submit">
<input type="submit" value="SEND" id="btn" />
</p>
Your problem is here:
function removeItem(e) {
var elElement = document.getElementsByTagName("li");
var elContainer = elElement.parentNode;
elContainer.removeChild(elElement);
}
This document.getElementsByTagName return an HTMLElementCollection which does not have the a property called parentNode. An element from that collection would.
To avoid the undefined error, you need to check if your object is null or undefined before trying to call a method on in such as .removeChild.
In your case, elContainer is null because the elElement is an HTMLElementCollection which doesn't have the .parentNode property.
You can access elements in the collection by index. It also has a length property which you should check to make sure that the collection has elements.
So if you want to remove the first LI, they you can do it like this.
function removeItem(e) {
var elements= document.getElementsByTagName("li");
if (elements.length==0) return;
var elElement = elements[0];
var elContainer = elElement.parentNode;
elContainer.removeChild(elElement);
}
So if you want to remove the that last LI, they you can do it like this.
function removeItem(e) {
var elements= document.getElementsByTagName("li");
if (elements.length==0) return;
var elElement = elements[elements.length-1];
var elContainer = elElement.parentNode;
elContainer.removeChild(elElement);
}