Im making a note taking application and the idea here is im trying to make a selection function to transfer my notes from the side list to the editor on the right side of the screen when clicked. So I have the list items all being created dynamically while the ul is created static.
The trouble im facing is how hard it is to click the list items. I have it console.log the work "click' whenever it registers and im not sure why its not working like its suppose it it looks like it only registers when I click the margins of the children of the li and not the h1 or p tags. Also if I click to the side, it makes my ul clickable which is not good as it would just throw everything in the editor.
I have it so when the li tags are created. It dynamically creates then via JS, adds li,h1,p,p. Appends the h1,p,p tags to the li then the li to the container.
Below is an example of my code:
//This is just to show you what happens when you click
//the submit button and how my divs are being dynamically created.
//I have them being created automatically from
//localstorage on load as well in this same fashion.
submitbutton.addEventListener('click', () => {
//Creating local variables for new notes
let NewNoteContainer = document.createElement('li')
let NewNoteTitle = document.createElement('h1')
let NewNoteDueDate = document.createElement('p')
let NewNoteContent = document.createElement('p')
let RemoveButton = document.createElement('button')
//Adds values of the input boxes to the newley created Elements
NewNoteContainer.id = NoteID
NewNoteContainer.className = 'notes-list-item'
NewNoteTitle.innerHTML = title.value
NewNoteDueDate.innerHTML = dueDate.value
NewNoteContent.innerHTML = content.value
//This appends the newly created elements to the container and then
//Appends the container to its div "note-list-container"
NewNoteContainer.append(NewNoteTitle, NewNoteDueDate,NewNoteContent)
NoteListContainer.append(NewNoteContainer)
//Creates an array, makes it a JSON string. Then stores it in localStorage
let StorageArray = [NoteID,title.value,dueDate.value,content.value]
localStorage.setItem('Note' + NoteID, JSON.stringify(StorageArray))
NoteID += 1
})
//This is the debug function im using to try and diag the click issue.
NoteListContainer.addEventListener('click', (a) => {
if(a.target.parentNode.className == 'notes-list-container') {
console.log('click')
}
})
Related
Use case is to create Add/show/select/delete text messages on a page. I have used array to store the messages on each click till here it works fine but when I try to create Divs and show the messages in grid, I am having duplication on each click. I can see that my function is reading the array fine and creating the div's on the first click but it does not clear the previously created div on second iteration. Not sure how to approach this. Please advise.
here is the snippet.
<script>
//<!-- Fetch data from Textarea when user Click Save and create or push in an array -->
let ArrNotes = [];
function SaveNote() {
let edittext = document.getElementById("editor").value;
ArrNotes.push(edittext);
document.getElementById("SavedNote").innerHTML = ArrNotes;
let container = document.getElementById("GridNotes");
container.className= "GridNotes";
ArrNotes.forEach(createGrid);
function createGrid(item,index)
{
text = undefined;
var tag = document.createElement("div");
tag.className= "grid";
var text = document.createTextNode(index + ": " + item);
//tag.appendChild(text);
container.appendChild(text);
}
}
I am currently trying to implement the page layout change with js onclick of the function, and the question is, how do I make the js display the current body html?
The logic is as following:
first I have my page html and the body dom, then I have the script where I define that if you click on the button then you have different content displayed, using the pageLayout.innerHTML = "<p>this is the new content</p>".
But how do I make the js display back the last content, or be back to the content that is defined on top of the script in the body without copy pasting it twice in the end with the same function?
You can store the previous content in a global variable, before making any changes.
So if you want the same button to revert the content you can do something like this:
let previousContent = "";
function handleClick() {
// Find the element that you want to change its content
const pageLayout = document.getElementById("layout");
// Check if there is any stored content
if(previousContent) {
pageLayout.innerHTML = previousContent;
//Clear the stored content
previousContent = "";
} else {
// Store the previous content
previousContent = pageLayout.innerHTML;
//Create the new content
const newContent = " your new content";
//Update the content
pageLayout.innerHTML = newContent;
}
}
const button = document.getElementById("my-button-id");
button.addEventListener("click", handleClick);
I created a meme generator that accepts text and images and puts them all together. The generator creates a unique ID for each 'meme' and also adds buttons that show up on hover to "delete" the meme. I used vanilla JS to create this and therefore had to layer a few different child divs on top of one another: image, top text, bottom text using z-index.
I am struggling, however, to get the button to delete the parent div. I want to be able to click that delete button, and have the parent div deleted so that the button goes away, along with image and text. picture below + code snippets.
I attemped to do it with vanilla javascript, by adding a closeTheMeme function on click to each button:
let deleteBtns = document.getElementsByClassName('.delete');
function closeTheMeme (){
this.parentElement.parentElement.removeChild();
};
for(let i=0;i<deleteBtns.length;i++){
deleteBtns[i].addEventListener("click",closeTheMeme);
}
No errors on console...Including the rest of the JS below so you can see how the elements are created on click of the meme generator.
'use strict';
let count=0;
// SUBMIT FORM
document.getElementById('memeInput').addEventListener('submit',function(e){
count++;
//prevent default
e.preventDefault();
//set image, top, and bottom to variables we can work with
let bottomText = document.getElementById('bottomText').value;
createMeme();
})
function createMeme(){
//create a meme section with an ID of the number of times the button was clicked, and add it to the meme section
let meme = document.createElement("DIV");
document.body.appendChild(meme);
meme.setAttribute("id", "meme"+count);
//create an image, set that image to equal the link, give it an id based on form submits, set image.src equal to the link
let img = document.createElement("IMG");
img.setAttribute("id","image"+count);
let imageLink = document.getElementById('imageLink').value;
meme.appendChild(img);
document.getElementById("image"+count).src=imageLink;
//set top text variable equal to the ID of toptext. value(form submission)
let topText = document.getElementById('topText').value;
let top = document.createElement('DIV');
top.setAttribute("id","topText"+ count);
meme.appendChild(top);
top.innerHTML = topText;
//set bottom text variable equal to the ID of toptext.value form submission
let bottomText = document.getElementById('bottomText').value;
let bottom = document.createElement('DIV');
bottom.setAttribute("id","bottomText" + count);
meme.appendChild(bottom);
bottom.innerHTML = bottomText;
//add a button that deletes the meme in the same way as above
let deleteButton = document.createElement("BUTTON");
deleteButton.classList.add("delete");
deleteButton.innerHTML = "Delete";
meme.appendChild(deleteButton);
//styling and position
meme.classList.add("meme");
top.classList.add("topWords");
bottom.classList.add("bottomWords");
};
let deleteBtns = document.getElementsByClassName('.delete');
function closeTheMeme (){
this.parentElement.parentElement.removeChild();
};
for(let i=0;i<deleteBtns.length;i++){
deleteBtns[i].addEventListener("click",closeTheMeme);
}
You select the buttons when the page loads. You created no buttons so it is not possible for it to work since there is nothing to bind an event to.
Since you are making the buttons, add the event there.
const deleteButton = document.createElement("BUTTON");
deleteButton.addEventListener("click", function () {
this.closest("div").remove();
});
Other option is event delegation
document.body.addEventListener("click", function (e) {
const btn = e.target.closest(".delete");
if (btn) btn.closest("div").remove();
});
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>
I'm currently building a small Todo list application using vanilla Javascript but I'm having some issues creating a delete button that onClick removes it's parent element.
From what I have read, when an onClick is called in Javascript the this keyword can be used to refer to the element that called the function. With this in mind I have the following code:
window.onload = initialiseTodo;
function addRecord(){
var title = document.getElementById('issueTitle');
var issueContent = document.getElementById('issueContent');
var contentArea = document.getElementById('contentArea');
if(title.value.length > 0 && issueContent.value.length > 0){
var newItem = document.createElement('div');
newItem.id = 'task' + count++;
newItem.className = 'task';
newItem.innerHTML = '<div class="taskbody"><h1>' + title.value + '</h1>'+ issueContent.value + '</div><div class="deleteContainer">'
+ '<a class="delete">DELETE</a></div>';
contentArea.appendChild(newItem);
assignDeleteOnclick();
}
}
function deleteRecord(){
this.parentNode.parentNode.parentNode.parentNode.removeChild(this.parentNode.parentNode);
}
function assignDeleteOnclick(){
var deleteArray = document.getElementsByClassName('delete');
for(var i=0;i<deleteArray.length;i++){
deleteArray[i].onclick= deleteRecord();
}
}
function initialiseTodo(){
var btn_addRecord = document.getElementById('addRecord');
btn_addRecord.onclick = addRecord;
}
Basically I have a form that has two fields. When these fields are filled and the addRecord button is clicked a new div is added at the bottom of the page. This div contains a delete button. After the creation of this I assign an onclick event to the delete button which assigns the deleteRecord function when the delete button is clicked. My issue is with the deleteRecord function. I have used this to refer to the calling element (the delete button) and wish to remove the task div that is the outermost container however I current get a message that says: 'Cannot read property 'parentNode' of undefined ' which suggests to me the this keyword is not working correctly.
Any help would be greatly appreciated.
I've added the full code to a fiddle.
http://jsfiddle.net/jezzipin/Bd8AR/
J
You need to provide the element itself as a parameter. I did so by changing the html to include onclick="deleteRecord(this)" to make it a little easier to deal with. This means you can remove the assignDeleteOnclick() function
function deleteRecord(elem){
elem.parentNode.parentNode.remove();
}
Demo
You might style the .content to be hidden better if there are no elements to prevent that extra white space
Edit
Since you don't want an inline onclick, you can do it with js the same:
function deleteRecord(elem){
elem.parentNode.parentNode.remove();
}
function assignDeleteOnclick(){
var deleteArray = document.getElementsByClassName('delete');
for(var i=0;i<deleteArray.length;i++){
// Has to be enveloped in a function() { } or else context is lost
deleteArray[i].onclick=function() { deleteRecord(this); }
}
}
Demo