When I append an element it does it twice rather than once - javascript

I am trying to make multiple comment boxes for a website. The first click to create the text area and submit button works fine. However when I click another it appends the text area and submit button twice - creating two text areas and submit buttons and then three and so on..
If you go to https://alexpd93.github.io/FAC-Website/ and click on various comment buttons it should make more sense.
I would like it so that each time I click on the comment button, it only creates one text area for each section.
How can I fix this?
function addComment(element) {
const boxContainer = element.parentNode.parentNode.parentNode;
const commentContainer = element.parentNode;
commentContainer.classList.add("comment-container-after-click");
const commentBox = document.createElement("textarea");
commentBox.classList.add("comment-box-after-click");
commentBox.placeholder = "What are your thoughts?";
commentBox.innerHTML = "";
const submitComment = document.createElement("button");
submitComment.classList.add("submit-comment-after-click");
submitComment.innerHTML = "Comment";
commentContainer.append(commentBox, submitComment);
submitComment.onclick = function submitComment() {
let comment = commentBox.value;
const newComments = document.createElement("p");
boxContainer.appendChild(newComments);
newComments.innerHTML = `${comment}`;
commentBox.value = "";
};
}
function comment(event) {
const commentButton = event.target;
commentButton.style.display = "none";
const commentIcon = document.getElementsByClassName("comment-icon");
const iconArray = Array.from(commentIcon);
iconArray.forEach((icon) => {
if (icon.nextElementSibling.style.display === "none") {
icon.style.display = "none";
addComment(commentButton);
}
});
}
<div class="comments-container" id="comments">
<img id="commentIcon" class="comment-icon" src="Images/Comment.png" alt="comment icon">
<button class="comment-button" id="commentButton" onclick="comment(event)" > Comment </button>
</div>

After playing around with the website I believe I understood the problem. You are calling addComment() for all elements with class comment-icon. And due to your (tbh) little bit weird handling of addComment() this adds a comment to every single one of this elements.
I've corrected the error below and marked my changes with comments.
function addComment(element) {
const boxContainer = element.parentNode.parentNode.parentNode;
const commentContainer = element.parentNode;
commentContainer.classList.add("comment-container-after-click");
const commentBox = document.createElement("textarea");
commentBox.classList.add("comment-box-after-click");
commentBox.placeholder = "What are your thoughts?";
commentBox.innerHTML = "";
const submitComment = document.createElement("button");
submitComment.classList.add("submit-comment-after-click");
submitComment.innerHTML = "Comment";
commentContainer.append(commentBox, submitComment);
submitComment.onclick = function submitComment() {
let comment = commentBox.value;
const newComments = document.createElement("p");
// why append to the box container? Then all comments from different textareas will be merged
// boxContainer.appendChild(newComments);
commentContainer.appendChild(newComments);
newComments.innerHTML = `${comment}`;
commentBox.value = "";
};
}
function comment(event) {
const commentButton = event.target;
commentButton.style.display = "none";
const commentIcon = document.getElementsByClassName("comment-icon");
// add the comment once not to every comment box available
addComment(commentButton);
const iconArray = Array.from(commentIcon);
iconArray.forEach((icon) => {
if (icon.nextElementSibling.style.display === "none") {
icon.style.display = "none";
// this causes that the comment is added multiple times
// addComment(commentButton);
}
});
}
<div div="all-comments">
<div class="comments-container" id="comments">
<img id="commentIcon" class="comment-icon" src="https://dummyimage.com/100x100/000/fff" alt="comment icon">
<button class="comment-button" id="commentButton" onclick="comment(event)"> Comment </button>
</div>
<div class="comments-container" id="comments">
<img id="commentIcon" class="comment-icon" src="https://dummyimage.com/100x100/000/fff" alt="comment icon">
<button class="comment-button" id="commentButton" onclick="comment(event)"> Comment </button>
</div>
<div class="comments-container" id="comments">
<img id="commentIcon" class="comment-icon" src="https://dummyimage.com/100x100/000/fff" alt="comment icon">
<button class="comment-button" id="commentButton" onclick="comment(event)"> Comment </button>
</div>
</div>

Related

Change image based on selected option on Piotnet Forms (Wordpress plugin)

I'm currently fighting with show images based on the selected option on the Piotnet Forms (WordPress plugin).
I'm not a programmer but I'm just trying to create something simple and useful for my friend.
<div>
<button id="btn0">0</button>
<button id="btn1">1</button>
<button id="btn2">2</button>
<button id="btn3">3</button>
</div>
<img src="https://test.ffd.sk/wp-content/uploads/2021/07/korpus4k1.png" alt="" id="image">
<script>
let image = document.querySelector("#image");
let btn0 = document.querySelector("#btn0");
let btn1 = document.querySelector("#btn1");
let btn2 = document.querySelector("#btn2");
let btn3 = document.querySelector("#btn3");
btn0.addEventListener("click", () => {
image.src = "https://test.ffd.sk/wp-content/uploads/2021/07/korpus4k1.png";
})
btn1.addEventListener("click", () => {
image.src = "https://test.ffd.sk/wp-content/uploads/2021/07/korpus1k1.png";
})
btn2.addEventListener("click", () => {
image.src = "https://test.ffd.sk/wp-content/uploads/2021/07/korpus2k1.png";
})
btn3.addEventListener("click", () => {
image.src = "https://test.ffd.sk/wp-content/uploads/2021/07/korpus20k1.png";
})
</script>
And other hand I made almost the same, but I want to change an image based on the radio button on the Piotnet form, and still not working. I used IDs but nothing.
Code for this option looks like this:
<img src="https://test.ffd.sk/wp-content/uploads/2021/07/korpus4k1.png" alt="" id="imageone">
<script>
let imageone = document.querySelector("#imageone");
let form-field-p12926701-0 = document.querySelector("#form-field-p12926701-0");
let form-field-p12926701-1 = document.querySelector("#form-field-p12926701-1");
let form-field-p12926701-2 = document.querySelector("#form-field-p12926701-2");
let form-field-p12926701-3 = document.querySelector("#form-field-p12926701-3");
form-field-p12926701-0.addEventListener("click", () => {
imageone.src = "https://test.ffd.sk/wp-content/uploads/2021/07/korpus4k1.png";
})
form-field-p12926701-1.addEventListener("click", () => {
imageone.src = "https://test.ffd.sk/wp-content/uploads/2021/07/korpus1k1.png";
})
form-field-p12926701-2.addEventListener("click", () => {
imageone.src = "https://test.ffd.sk/wp-content/uploads/2021/07/korpus2k1.png";
})
form-field-p12926701-3.addEventListener("click", () => {
imageone.src = "https://test.ffd.sk/wp-content/uploads/2021/07/korpus20k1.png";
})
</script>
Here is a link for the test page:
https://test.ffd.sk/java/
Thanks for any advice.

onload Function and Document Ready function in JS creating conflict

So I'm working on a section of my Website which has a TODO List built in not I want the data to load just like other data that are loading alongside the page. I tried having onload in Body Tag in my HTML and I had also tried to $(document).ready(function(){}) as well however neither of them seemed to work nor was I getting any errors in my console. But the function is working as it is also link to another function which runs on click of a button which I don't want to keep happening. I want it to be seamless. Is there any reason why this might not be working.
Thanks for any help in advance.
My HTML and Javascript Code:
function create() {
unfinished_task_container = document.getElementById("main_container");
unfinished_task_container.innerHTML = "";
var user = firebase.auth().currentUser;
var uid;
if (user != null) {
uid = user.uid;
}
task_array = [];
firebase
.database()
.ref("/Users/" + uid + "/todo/")
.once("value", (snapshot) => {
snapshot.forEach((childSnapshot) => {
var childKey = childSnapshot.key;
var childData = childSnapshot.val();
task_array.push(Object.values(childData));
});
for (var i = 0; i < task_array.length; i++) {
task_key = task_array[i][0];
task_title = task_array[i][1];
//Data
task_container = document.createElement("div");
task_container.setAttribute("class", "task_container");
task_container.setAttribute("data-key", task_key);
task_data = document.createElement("div");
task_data.setAttribute("id", "task_data");
title = document.createElement("p");
title.setAttribute("id", "task_title");
title.setAttribute("contenteditable", false);
title.innerHTML = task_title;
//Tools
task_tool = document.createElement("div");
task_tool.setAttribute("id", "task_tool");
task_done_button = document.createElement("button");
task_done_button.setAttribute("id", "task_done_button");
task_done_button.setAttribute(
"onclick",
"task_done(this.parentElement.parentElement, this.parentElement)"
);
task_done_button.setAttribute("onclick", "task_done()");
fa_done = document.createElement("i");
fa_done.setAttribute("class", "fa fa-check");
unfinished_task_container.append(task_container);
task_container.append(task_data);
task_data.append(title);
task_container.append(task_tool);
task_tool.append(task_done_button);
task_done_button.append(fa_done);
}
});
}
<body onload="create();">
<div class="dentistToDo">
<p class="divlable">Your Personal To Do List</p>
<input id="input_box" placeholder="What needs to be done?" />
<button id="input_button" onclick="add_task()">Add Task</button>
<div class="container" id="main_container">
<!-- DIV for TODO List -->
</div>
</div>

How can i add multi lines together into different different div / span tag through this text box?

How can i add multi lines together into different different span tag through this text box ?
There is an text box, by using this box i can insert a new div / span class content Right ?
But every time when i need to add new class i need to write a new line in this text box and need to press send button, Now i want that if i have 10 lines content together with "Enter" button line break
Like
My Line 1 is here
My Line 2 is here
My Line 3 is here
My Line 4 is here
My Line 5 is here
My Line 6 is here
My Line 7 is here
My Line 8 is here
... and so on
then i want to paste all 10 lines in this text box together and by pressing send button i want that all lines must be add in different different div / span class not all in one class with < br > tag that is working now.
so plz help me to improve my code
Love you Helper and Thanks in Advance
const sendButton = document.getElementById('send-btn');
const textArea = document.getElementById('input');
const innerDiv = document.getElementById('inner');
var message = textArea.value;
sendButton.addEventListener('click', function () {
const message = new MessageContainerBuilder().BuildMessage(textArea.value);
innerDiv.appendChild(message);
textArea.value = '';
});
function encodeHtmlEntity(input) {
var output = input.replace(/[\u00A0-\u9999<>\&]/gim, function (i) {
return '&#' + i.charCodeAt(0) + ';';
});
return output;
}
function MessageContainerBuilder() {
var createDivElement = function (classTest) {
var div = document.createElement('div');
var classAttr = document.createAttribute('class');
classAttr.value = classTest;
div.setAttributeNode(classAttr);
return div;
};
var createSpanElement = function (value, classTest) {
var span = document.createElement('span');
if (classTest) {
var classAttr = document.createAttribute('class');
classAttr.value = classTest;
span.setAttributeNode(classAttr);
}
span.innerText = encodeHtmlEntity(value);
return span;
};
this.BuildMessage = function (text) {
var divContainer = createDivElement('outgoing');
var messageSpan = createSpanElement(text, 'me');
divContainer.appendChild(messageSpan);
return divContainer;
};
}
<div id="inner">
<div class="incoming">
<div class="them">Lorem
</div>
</div>
<div class="outgoing">
<div class="me">Lorem ipsum
</div>
</div>
</div>
<textarea class="input" id="input" placeholder="Message..."></textarea>
<button class="waves-effect waves-light" id="send-btn">Send</button>
so plz help me to improve my code
Love you Helper and Thanks in Advance
I took some liberties and simplified your code as you can see below. It does everything I believe your code was attempting.
Note that I'm using .split("\n") to break your input based on each newline character and then iterate over that as necessary.
Also, you said you were inserting a div/span, but I don't see your code actually creating a span tag. I wrote my code to do that for you though.
const sendButton = document.getElementById('send-btn');
const textArea = document.getElementById('input');
const innerDiv = document.getElementById('inner');
var message = textArea.value;
sendButton.addEventListener('click', function() {
// split the textarea entries into an array
let lines = (textArea.value).split("\n");
// iterate over each line, creating a div/span and inserting into the DOM
lines.forEach( (line) => {
let encodedLine = encodeHtmlEntity(line);
let newElement = `<div class="me"><span>${encodedLine}</span></div>`;
innerDiv.innerHTML += newElement;
});
// reset the textarea
textArea.value = '';
});
function encodeHtmlEntity(input) {
var output = input.replace(/[\u00A0-\u9999<>\&]/gim, function(i) {
return '&#' + i.charCodeAt(0) + ';';
});
return output;
}
<div id="inner">
<div class="incoming">
<div class="them">Lorem
</div>
</div>
<div class="outgoing">
<div class="me">Lorem ipsum
</div>
</div>
</div>
<textarea class="input" id="input" placeholder="Message..."></textarea>
<button class="waves-effect waves-light" id="send-btn">Send</button>
You can try using String.prototype.split() so that each text is separated by \n (new line) into an array, then you can iterate over each element like using Array.prototype.forEach(). Here's the code you can use:
sendButton.addEventListener('click', function () {
textArea.value.split('\n').forEach((text) => {
const message = new MessageContainerBuilder().BuildMessage(text);
innerDiv.appendChild(message);
});
textArea.value = '';
});

Insert Image to div upon click

I want to be able to add an image to this div once the button is clicked and a check box is checked. I have already confirmed that the checkbox portion works properly, but can't get the photo to go into the div.
Here is what I currently have:
<button id="show_button">Show System</button>
<div class="box" id="AC1"></div>
<script>
var show_button = document.getElementById('show_button');
var show = function() {
// AC Relevant Components;
var ch_mGT = document.getElementById('mGT').checked;
// Set AC1
if (ch_mGT) {
var AC1_html = "<img src='http://localhost/....png' alt='Micro Turbine'
height='50px'>";
document.getElementById("AC1").innerHTML(AC1_html);
}
}
show_button.addEventListener("click",show);
</script>
I also have already tried:
var AC1_img = document.createElement("img");
AC1_img.src = 'http://localhost/....png'
document.getElementById('AC1').appendChild(AC1_img);
You said you tried using appendElement, but it seems to be working in the below example.
var show_button = document.getElementById('show_button');
var show = function() {
var ch_mGT = document.getElementById('mGT').checked;
var AC1_img = document.createElement('img')
AC1_img.src="https://i.ytimg.com/vi/r4Hve6fZ7ik/maxresdefault.jpg"
AC1_img.style.height = "50px"
AC1_img.alt = 'Micro Turbine'
if (ch_mGT) {
document.getElementById("AC1").appendChild(AC1_img)
}
}
show_button.addEventListener("click",show);
<div class="box" id="AC1"></div>
<input type="checkbox" id="mGT">
<button id="show_button">Show System</button>

create multiple arrays on different elements

I'm trying to set a function in my application which allows the user to click on a button and then click the submit button which displays an image, but I want the buttons to hold more than one image and randomly select an image from the array.
How can I do this?
<div id='prefPage'>
<header id='header2pref'>
<div id='title2pref'>PREFERENCES</div>
</header>
<div id='body'>
<div id='leftAlign'>
<div id="foodpicloc">
</div>
</div><button id='myBtn2'>SET PREFRENCES</button>
<div id='rightAlignPref'>
<div id=fixed>
<div>
<button id="button1">BURGER</button>
<button id="button2">HOTDOG</button>
</div>
</div>
</div>
</div>
</div>
var button1 = document.getElementById("button1");
var button2 = document.getElementById("button2");
var preference = document.getElementById("preference");
var foodpic = document.getElementById("foodpiclocation");
var foodpic;
button1.addEventListener('click', function() {
foodpicurl = 'burger.svg';
});
button2.addEventListener('click', function() {
foodpicurl = 'hotdog.svg';
});
preference.addEventListener('click', function() {
var foodpic = document.createElement('img');
foodpic.src = foodpicurl;
foodpiclocation.innerHTML = '';
foodpiclocation.appendChild(foodpic);
});
Clean solution using vanilla Javascript. NOTE: I suggest you add this to your HTML code <div id="foodpicloc"><img id="foodpic"></div> in your HTML first. Changing the image's src is quicker and cleaner than appending a new image element everytime the image changes.
Define
function mapClickToImage(imageSelector, updateBtnSelector, btnSectorToImageSrcMapping) {
var currentImageSrc = null;
var imageElement = document.querySelector(imageSelector);
for (var btnSelector in btnSectorToImageSrcMapping) {
var buttonElement = document.querySelector(btnSelector);
buttonElement.addEventListener('click', function() {
currentImageSrc = btnSectorToImageSrcMapping[btnSelector];
});
var updateButtonElement = document.querySelector(updateBtnSelector);
updateButtonElement.addEventListener('click', function() {
if (currentImageSrc) {
imageElement.src = currentImageSrc;
}
});
}
Usage
mapClickToImage('#foodpic', '#preference', {
'#button1': 'burger.svg',
'#button2': 'hotdog.svg'
});

Categories