This isn't a help me solve something kind of question rather a explain what this does type question.
I understand what parentNode does but I can't wrap my head around the context of how it works with my code. The reason I was able to write the code was through a YouTube tutorial.
I was learning how to create a todo list app where you were able to add stuff and remove it. I made the remove button but the code I don't understand is how the remove function works in the code.
By my understanding, I'm thinking that it deletes the child which is the LI from the parent which is the UL?
If someone could explain the removeItem() function and what the code does I would very much appreciate it.
var input = document.getElementById('input'),
button = document.getElementById('add')
function removeItem() {
var item = this.parentNode
var parent = item.parentNode
parent.removeChild(item)
}
button.addEventListener('click', function(e) {
var p = document.querySelector('p')
if (input.value.trim() === '') {
p.style.display = 'block'
return false
}
p.style.display = ''
var userInput = document.createTextNode(input.value)
var li = document.createElement('li')
var ul = document.getElementById('todo')
var remove = document.createElement('button')
remove.innerHTML = 'Remove'
remove.addEventListener('click', removeItem);
ul.insertBefore(li, ul.childNodes[0])
li.appendChild(userInput)
li.appendChild(remove)
})
<input type="text" id="input"/>
<button id="add">Add</button>
<p>plz add</p>
<ul id="todo"></ul>
You are correct. The best way to remove a node in Javascript is from its parent, using the removeChild() function.
You could use the remove() function like item.remove(), but this will not work with IE because in IE this function does another thing, it removes an option from a drop-down list (select).
So, to achieve cross-browser behavior, it is used the removeChild approach.
Related
I have a list with people's data inside it has a li element with 3 p tags inside, one for name, one for address and one for email.
I filled this list manually but due to some changes to my code I had to rewrite this so the html would be made with javascript.
My code looked like this
<p class="adres">#logopedist.Adres</p>
<p class="email">#logopedist.Email</p>
<p class="mobiel">#logopedist.Mobiel</p>
I rewrote this to build the html using javascript. This looks something like this.
var li = document.createElement('li');
li.className = "lijst";
li.id = "lijst";
li.onclick = "ficheVullen(this)";
p.className = "naam";
p.innerHTML = objLogos.Naam[i];
li.appendChild(p);
p.className = "adres";
p.innerHTML = objLogos.Adres[i];
li.appendChild(p);
var p = document.createElement('p');
p.className = "mobiel";
p.innerHTML = objLogos.Mobiel[i];
li.appendChild(p);
My list generates properly. But in my old code I had this at the start of the list.
<li class="lijst" onclick="ficheVullen(this)">
Whenever you would click an li element it would fill a div with the info from the p tags inside that li, so it would fill the div with name, address, mobile,etc
I cannot seem to get this function to work anymore. It only works on the very first LI element and only works for the name. Even though my code is the same and I append classes to the tags like it had in my old code.
The function looks like this:
function ficheVullen() {
FicheNaam = document.getElementById("FicheNaam");
FicheAdres = document.getElementById("FicheAdres");
FicheGSM = document.getElementById("FicheGSM");
FicheNaam.innerHTML = this.querySelector('.naam').textContent;
FicheGSM.innerHTML = this.querySelector('.mobiel').textContent;
FicheAdres.innerHTML = this.querySelector('.adres').textContent;
I get this error now. Cannot read property 'textContent' of null
I call this function here:
window.onload = function() {
changePage(1);
document.getElementById("lijst").addEventListener("click", ficheVullen);
};
The changepage function is part of my pagination where I use javascript to build the list.
When I move the eventlistener out of this I get this error: Cannot read property 'addEventListener' of null.
I hope this gives enough context
You have to use setAttribute to set id.
elm.setAttribute("id", "uniqueId");
Your case : li.setAttribute("id", "lijst")
li.id = "lijst"; will add "id" to object not as attribute
const parent = document.getElementById("container")
let elm = document.createElement("p")
elm.setAttribute("id", "pElm")
elm.innerText = "p tag"
parent.append(elm)
document.getElementById("pElm").style.background = "red"
<div id="container"></div>
Question: Why does it work when element is hard-coded into HTML but does not work when added dynamically via Jquery?
I am teaching my self Jquery within my self learning of javascript, and I am just creating a simple troubleshooting assistant app for the sake of learning.
I actually have my code posted here: https://repl.it/#jllrk1/OrganicBothRay.
The way I have it set up so far is the user clicks on the header block to begin, which is set up with a onetime click function to create a UL for some products at my job in which we provide IT Service.
I then am trying to be able to click each product in that list to pull troubleshooting walkthroughs for that specific product (it will guide the user based on what they click or enter).
For testing purposes I just tried having the background of the list item in which is clicked to change to red.
I cannot get this to work, or my console.log to fire telling me that the function is not getting called.
however, if I hard code in the ul into the html, using the same code for the click events, it works just fine.
Am I doing something wrong?
Just looking to gain a better understanding!
$(function () {
//*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_
//set up variables
//*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_
//var $liItems = $('.product li');
var $chief = $(".chiefblock");
var $container = $("#container");
var $this = $(this);
var $error = '';
var initList = function () {
console.log("initList initiated");
$container.append('<div class="product"><ul><li>TASC</li><li>TABE</li><li>Las Links</li><li>TerraNova</li><li>E-Direct</li></ul></div>');
$("p").text("Start by selecting a product");
}
var navItems = function (event){
console.log("navItems initiated");
var target = $(event.target);
if (target.is("li") ) {
target.css("background-color", "red" );
}
}
var nObject = function () {
$container.append('<div id = "tasc"><h2>Tasc</h2><p></p></div></div>');
$('#newItem').prepend('<h2>Item</h2>');
}
$('.chiefblock').one('click', initList)
//$('li').on('click', navItems) this i tried and does not work
$('#newObject').on('click', nObject)
$('ul').on('click', navItems)
//$liItems.on('click', navItems)this i tried and does not work
});
for dynamically added DOM elements use
$(document).on('click', '#element', function() {
console.log($(this))
})
I'm trying to put a delete button on each li using JavaScript and to make an event handler that runs when a button is clicked that removes the li. However when I try to add the handler, I get:
Cannot read property 'addEventListener' of null
I think this is because I am referencing a class that not exist before run the function createbtn. So How can I solve this?
The Code:
I set the variables, put querySelector to buttons because I testing how to do it:
var button = document.getElementById("enter");
var input = document.getElementById("userinput");
var ul = document.querySelector("ul");
var list = document.querySelectorAll ("li");
var buttons = document.querySelector (".btn-danger");
var li = document.createElement("li")
How I create the button:
function createbtn() {
for (var i = 0; i < list.length; i++) {
var btn = document.createElement("button");
btn.appendChild(document.createTextNode("Delete"));
btn.classList.add("btn", "btn-danger","btn-sm");
list[i].appendChild(btn);
}
}
The function I try to run:
function liDel(){
li.parentNode.removeChild(li);
}
buttons.addEventListener("click", liDel);
This is my fiddle to see all the code.
The reason why you are getting the null error is because;
You have assigned the variable buttons to a node which doesn't exist yet. (Note that the button is created after the page has been loaded, which means .btn-danger hasn't yet been created at that time).
According to MDN the querySelector method does the the ff:
The Document method querySelector() returns the first Element within the document that matches the specified selector, or group of selectors. If no matches are found, null is returned.
Based on the code you have in the fiddle, here is a guide to achieve the desired results.
First of all, get rid of the global li variable on line 6.
The reason is that if you create a new li from the input, it will render on the same line because it's still referencing the same element node (I'm sure you've realized that)
then in your createListElement function, do the ff
function createListElement() {
var li = document.createElement('li');
li.appendChild(document.createTextNode(input.value));
var btn = document.createElement("button");
btn.appendChild(document.createTextNode("Delete"));
btn.classList.add("btn", "btn-danger","btn-sm");
btn.addEventListener('click', function(e){
if(!e) e = window.event;
try{
ul.removeChild(this.parentNode)
}catch(err){
alert(err.message)
}
})
li.appendChild(btn)
ul.appendChild(li);
input.value = "";
}
Then when you create the buttons, you have to attach the event listener function to it. So you do the ff in your createbtn function:
// To create a button
function createbtn() {
for (var i = 0; i < list.length; i++) {
var btn = document.createElement("button");
btn.appendChild(document.createTextNode("Delete"));
btn.classList.add("btn", "btn-danger","btn-sm");
btn.addEventListener('click', function(e){
if(!e) e = window.event;
try{
ul.removeChild(this.parentNode)
}catch(err){
alert(err.message)
}
})
list[i].appendChild(btn);
}
}
anyways, there are more efficient ways to do this. But this is a quick workable model based on the code in your fiddle
Rather than querying and adding the event to the buttons object
try the chaining inside the document load.
window.onload = function () {
document.querySelector('.btn-danger').addEventListener('click', liDel);
};
The above code should work!
Thanks a lot everybody, I got a solution after reading all your answers:
First I got rid the following:
var buttons = document.querySelector (".btn-danger");
var li = document.createElement("li")
Then create this function for remove the "li"
Using "this" you avoid the error for don't have a reference, because with that you don't care in what kind of element this is, you only now something is there and grab it for anything you need.
function liDel(){
ul.removeChild(this.parentNode);
}
and put this in createBtn for delete the existing "li" in the html:
btn.addEventListener('click', liDel);
then put this on createElement for do the same of the above, but for the new "li" creates with the DOM:
btn.addEventListener('click', liDel);
li.appendChild(btn);
And with that the problems was solved.
Thanks again and you can see how the page works on the fiddle
I have an issue, happening in IE and Chrome...I am creating an autocomplete text box, using JSON values...
It is going as planned, apart from something I cannot work out...I am trying to wire an onclick up to each new span element that I am creating before appending it to the main autocomplete div.
var deserialized = JSON.parse(json);
for (var el in deserialized) {
var span = document.createElement("span");
var txtForSpan = document.createTextNode(deserialized[el]);
span.appendChild(txtForSpan);
span.appendChild(document.createElement("br"));
elem.appendChild(span);
}
elem.style.display = "inline-block";
I have tried:
span.onclick = function(){alert("hi");}
and also:
span.addEventListener('click', function() {alert("hi");});
and even:
span.onclick = alertMe;
Can anyone shed any light on this?
Many Thanks.
Thanks for the responses everyone, epascarello, your answer helped me work out what was wrong.
It turns out that the 'onblur' event, which I have on my textbox, is firing before the onclick of the appended spans.
To get round this, I have used a small timeout before the onblur event fires in order to let onclick fire first....not ideal, but it works pretty well...
Textbox:
onblur="hide()"
Which calls:
function hide(){
setTimeout(function() {
var elem = document.getElementById("completebox");
elem.style.display = "none";
elem.textContent = "";
}, 300);}}
I hope it's not a problem to post much specific code here, but I figure it will be better explained if everyone can just see it, so I will give you my code and then I will explain my problem.
My code:
function addBeGoneLinks () {
var beGoneClassElems;
var beGoneSpan;
var beGoneLink;
var beGonePrintSafe;
var spacesSpan;
//var middotSpan = document.createElement ('span');
var interactionContainer = document.getElementsByClassName('feedItemInteractionContainer');
for (var i=0; i<children.length; i++)
{
beGonePrintSafe = false;
beGoneClassElems = children[i].getElementsByClassName('beGone')
beGonePrintSafe = true;
if (beGoneClassElems.length == 0)
{
beGoneLink = document.createElement('a');
beGoneLink.href = 'javascript:void(0);';
beGoneLink.appendChild(document.createTextNode('Be Gone'));
beGoneLink.className = 'beGone';
beGoneLink.id = 'beGoneLink' + i.toString();
beGoneLink.addEventListener ("click", function() {beGone();}, false);//This line!
beGoneLink.align = 'right';
spacesSpan = document.createElement('span');
spacesSpan.innerHTML = ' - ';
if (interactionContainer[i] != undefined)
{
interactionContainer[i].appendChild(spacesSpan);
interactionContainer[i].appendChild(beGoneLink);
}
}
}
}
Here I have a function from a Greasemonkey script that I am working on. When one of the links is clicked, my aim is to have it call the function beGone() which will, among other things, remove the whole element a few parents up, thereby removing their sibling's, their parents and their parents' siblings, and one or two levels after that.
My idea was just to get the id of the link that was pressed and pass it to beGone() so that I could then get the parents using its id, but I do not know how to do that. Am I able to have the id of a link passed by the function that it calls? If not, is there any other way to do this?
I am not sure whether I am missing some really simple solution, but I haven't been able to find one rooting around the web, especially because I was unsure how I would search for this specific problem.
Try this:
beGoneLink.addEventListener("click", beGone, false);
beGone = function (evt) {
evt.target; // evt.target refers to the clicked element.
...
}
You can then use evt.target.id, evt.target.parentNode, etc.