How to insert html element inside the index.html from javascript - javascript

I want to insert the card into container using javascript. How do I do it. or make those card display in flex. So it's not like shown in below pic. I have used insertAdjancentHTML to insert the data in note class using javascript. However i'm unable to put them in container.
const addBtn = document.getElementById("add");
const addNewNote = (text = "") => {
const note = document.createElement("div");
note.classList.add("note");
const htmlData = `<div class="card m-4" style="width: 18rem">
<div class="card-body">
<div class="d-flex justify-content-between">
<h5 class="card-title">Card title</h5>
<span class="icons">
<button class="btn btn-primary">
<i class="bi bi-pencil-square"></i>
</button>
<button class="btn btn-primary">
<i class="bi bi-trash"></i>
</button>
</span>
</div>
<hr />
<p class="card-text">
Some quick example text to build on the card title and make up the
bulk of the card's content.
</p>
</div>
</div>`;
note.insertAdjacentHTML("afterbegin", htmlData);
console.log(note);
document.body.appendChild(note);
};
addBtn.addEventListener("click", () => {
addNewNote();
});

Firstly, just use innerHTML - it's an empty element:
note.innerHTML = htmlData;
Secondly, you need to select the element to append this note to. Add an ID:
<div class="container d-flex" id="noteContainer">
And append it like so:
document.getElementById("noteContainer").appendChild(note);

You can add an identifier to the div an use the appendChild to this div instead of the body of the document
<div id="myDiv" class="container d-flex"></div>
And at the end of your function
document.getElementById("myDiv").appendChild(note);
Working example
const button = document.getElementById("addButton")
const addNote = () => {
const myElement = document.createElement('p')
myElement.innerHTML = "Hello world !"
const div = document.getElementById("myDiv")
div.appendChild(myElement)
}
button.addEventListener("click", addNote)
<button id="addButton">Add element</button>
<div id="myDiv"></div>

Cache the container element.
Return the note HTML from the function (no need to specifically create an element - just wrap the note HTML in a .note container), and then add that HTML to the container.
(In this example I've used unicode for the icons, and a randomiser to provide some text to the note.)
const container = document.querySelector('.container');
const addBtn = document.querySelector('.add');
function createNote(text = '') {
return`
<div class="note">
<div class="card m-4" style="width: 18rem">
<div class="card-body">
<div class="d-flex justify-content-between">
<h5 class="card-title">Card title</h5>
<span class="icons">
<button class="btn btn-primary">🖉</button>
<button class="btn btn-primary">🗑</button>
</span>
</div>
<hr />
<p class="card-text">${text}</p>
</div>
</div>
</div>
`;
};
function rndText() {
const text = ['Hallo world', 'Hovercraft full of eels', 'Two enthusiastic thumbs up', 'Don\'t let yourself get attached to anything you are not willing to walk out on in 30 seconds flat if you feel the heat around the corner'];
const rnd = Math.round(Math.random() * ((text.length - 1) - 0) + 0);
return text[rnd];
}
addBtn.addEventListener('click', () => {
const note = createNote(rndText());
container.insertAdjacentHTML('afterbegin', note);
});
<div>
<button type="button" class="add">Add note</button>
<div class="container"></div>
</div>

Related

how to add same nodes two times with append()?

I want to add node named as card into container two times but the way1 didn't worked.
So i solved way2. But it looks like not good code. so i want to anohter way
Please teach me.
html
<div class="container">
<div class="row">
<div class="col-sm-4">
<img src="https://via.placeholder.com/600" class="w-100">
<h5 class="title">Card title</h5>
<p class="price">price : 70000</p>
</div>
</div>
</div>
js //way1 didn't added two times
let card = document.querySelector('.row').cloneNode(true) //want to add in container two times
let container = document.querySelector('.container');
container.append(card)
container.append(card)
js //way2 to solve but doesn't look good
let card = document.querySelector('.row').cloneNode(true);
let card2 = document.querySelector('.row').cloneNode(true);
let container = document.querySelector('.container');
container.append(card, card2)
You have to 're-clone' the row to be able to append it again. You can't append the same elements again. Try using a clone function, something like
const container = document.querySelector(`.container`);
const cloneRow = _ =>
document.querySelector(`.container .row:first-child`).cloneNode(true);
container.append(cloneRow());
container.append(cloneRow());
<div class="container">
<div class="row">
<div class="col-sm-4">
<img src="https://via.placeholder.com/50" class="w-100">
<h5 class="title">Card title</h5>
<p class="price">price : 70000</p>
</div>
</div>
</div>
Alternative is to use the html of the row to copy/append:
const container = document.querySelector(`.container`);
const nwRow = document.querySelector(`.row`).innerHTML;
// add 5 rows
for (let i = 0; i < 5; i += 1) {
container.append(
Object.assign(
document.createElement(`div`),
{className: `row`, innerHTML: nwRow} ) );
}
<div class="container">
<div class="row">
<div class="col-sm-4">
<img src="https://via.placeholder.com/50" class="w-100">
<h5 class="title">Card title</h5>
<p class="price">price : 70000</p>
</div>
</div>
</div>

I apply addevent listener on multiple items and also make the content editable, but it didn't worked?

I am trying to make the note title editable when someone clicks on it.
It worked when applied on a single note but its (contenteditable) function is not working on all elements.
Here is the javascript code:
let notecardTitle = document.getElementsByClassName("cardtitle");
for(let i = 0 ; i < notecardTitle.length ; i++){
notecardTitle[i].addEventListener("click", function changeTitle(e) {
console.log("change", e);
notecardTitle.contentEditable = 'true';
});
}
I am applying this event-listener on this note which is also made in javascript
let showBox = "";
noteData.forEach(function(element, index) {
showBox += `<div class="noteCard my-2 mx-2 card" style="width: 18rem;">
<div class="card-body">
<h5 class="cardtitle">Note
${index + 1}
</h5>
<p class="card-text">
${element}
</p>
<button id="${index}" onclick="deleteNote(this.id)" class="btn btn-primary">Delete Note</a>
</div>
</div> `
})
Leave the NoteData line. This is the code on which i am applying event-listener <h5 class="cardtitle">Note
Thanks

How can I add elements in JS to certain divs

How do I put the created input into the other div in situation I presented below? If I introduce divs in js like this - '<div class="monday_input"><input type="button" class="remove_button" value="-" onclick="removeMon(this)" /></div>' removing the whole element is not working for some reason in this specific case. Answering the question. No I cannot create div in parent in html because input won't magically suit to created div . Please help me somehow, thank you!
HTML:
<div class="day">
<div class="day_info">
<p>Monday</p>
</div>
<div class="add">
<div class="button" onclick="add_monday()">
<i class="fas fa-plus" id="plus"></i>
</div>
</div>
<div style="clear:both"></div>
</div>
<div id="mon">
<div style="clear:both"></div>
</div>
JavaScript:
Function to adding:
function add_monday() {
if (monday_sub_count < 5) {
monday_sub_count++;
{
const mon = document.createElement('div');
mon.className = 'subcategory';
mon.innerHTML = '<textarea name="monday'+monday_id_count+'" placeholder="Type anything you want here" class="subcategory_text"></textarea><input type="button" class="remove_button" value="-" onclick="removeMon(this)" />';
monday_id_count++;
document.getElementById('mon').appendChild(mon);
}
}
}
Function to removing:
function removeMon(mon) {
document.getElementById('mon').removeChild(mon.parentNode);
monday_sub_count--;
monday_id_count--;
};
with your own HTML
function add_monday() {
var monday_sub_count = 0;
var a;
while (monday_sub_count < 5) {
a = '<div><textarea name="monday'+monday_id_count+'" placeholder="Type anything you want here" class="subcategory_text"></textarea><input type="button" class="remove_button" value="-" onclick="removeMon(this)" /></div>';
monday_sub_count++;
$('#mon').append(a);
}
}
Here is working, "proper" version of your code. I think your problem may come from over-complicating the removal process.
function add_monday()
{
let monday_count = 0;
// Use DocumentFragment for marginal optimizations
let fragment = new DocumentFragment();
while(monday_count < 5)
{
let monday = document.createElement('div');
monday.classList.add('subcategory');
let textarea = document.createElement('textarea');
textarea.classList.add('subcategory_text');
textarea.name = "monday_"+monday_count;
textarea.placeholder = "Type anything you want here";
let removeBtn = document.createElement('input');
removeBtn.type = "button";
removeBtn.classList.add('remove_button');
removeBtn.value = "-";
removeBtn.addEventListener('click', removeMon.bind(null, removeBtn));
monday.append(textarea, removeBtn);
fragment.appendChild(monday);
monday_count++;
}
document.getElementById('mon').appendChild(fragment);
}
function removeMon(button)
{
button.parentElement.remove();
}
I simplified your script a little and changed your name attributes: Instead of assigning individual names I simply gave all textareas the name monday[]. When posting this to a PHP page the values will be pushed into an array with the same name and in case you want to harvest the values with JavaScript, then this can be done easily too.
function add_monday(){
$("#mon").append('<div><textarea name="monday[]" placeholder="Type anything you want here"></textarea><input type="button" value="-"/></div>'.repeat(5))
}
$("#mon").on("click","input[type=button]",function(){$(this).parent(). remove()})
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<div class="day">
<div class="day_info">
<p>Monday</p>
</div>
<div class="add">
<div class="button" onclick="add_monday()">
<i class="fas fa-plus" id="plus">click here to add fields</i>
</div>
</div>
<div style="clear:both"></div>
</div>
<div id="mon">
<div style="clear:both"></div>
</div>
And here a non-jQuery version:
const ad=document.querySelector(".alldays");
ad.innerHTML=
"Mon,Tues,Wednes,Thurs,Fri,Satur,Sun".split(",").map(d=>`
<div class="day">
<div class="day_info"><p>${d}day</p></div>
<div class="add">
<div class="button">
<i class="fas fa-plus" id="plus">click here to add fields</i>
</div>
</div>
<div style="clear:both"></div>
</div>
<div id="${d.toLowerCase().substr(0,3)}">
<div style="clear:both"></div>
</div>`).join("");
function add2day(el,n){
const wd=el.closest(".day"),
d=wd.querySelector("p").textContent.toLowerCase(),
html=`<textarea name="${d.toLowerCase()}[]" placeholder="Type anything you want here"></textarea><input type="button" value="-"/>`;
while (n--) {
let div= document.createElement("div");
div.innerHTML=html;
wd.nextElementSibling.appendChild(div);
}
}
ad.addEventListener("click",function(ev){
const el=ev.target;
switch(el.tagName){
case "INPUT": // remove field
el.parentNode.remove(); break;
case "I": // add new fields
add2day(el,3); break;
}
})
<div class="alldays"></div>
I extended the second script to make it work for any day of the week.

How do I apply the same logic to multiple repeated elements?

I am trying to add the same drop down functionality to an amount n of "cards". How could I do this in javascript without having to create new code for each card?
This is my current code that I have tried, but even if I got this working it would only work for the first card: (working example below)
my html:
<div class="ideanode">
<div class="ideanodeheader">Need</div>
<div class="content">
<div class="title">
<h3 contenteditable="True" onclick='this.focus();'>Title</h3>
</div>
<i class="fas fa-sort-down title-arrow"></i>
<div class="maintext">
<textarea placeholder="Text" class="maintextinput"></textarea>
</div>
<i class="fas fa-sort-down maintxt-arrow"></i>
<div class="comments">
<textarea placeholder="Comments" class="commentsinput"></textarea>
</div>
</div>
</div>
js:
var maintxt = document.querySelector(".maintext");
var title = document.querySelector(".title");
var titleArrow = document.querySelector(".title-arrow");
var mainArrow = document.querySelector(".maintxt-arrow");
var comments = document.querySelector(".comments");
var mainArrows = document.querySelectorAll(".maintxt-arrow")
titleArrow.addEventListener('click', function() {
maintxt.classList.toggle("hidden");
mainArrow.classList.toggle("hidden");
if (comments.classList.contains("hidden")){
;
} else {
comments.classList.toggle("hidden");
};
});
mainArrow.addEventListener("click", function() {
comments.classList.toggle("hidden");
});
Example: https://codepen.io/ricodon1000/pen/Baoxwed
I would like for the dropdown arrows to trigger the boxes below them, the upper arrow should trigger only the box below it on, but if both boxes are open both should be closed. The arrow that is below should only trigger the box directly below it on and off (display: none on and off).
Do the same for each node, and limit your querySelector to the group
const ideanodes = [...document.querySelectorAll('.ideanode')];
ideanodes.forEach(ideanode => {
const maintxt = ideanode.querySelector(".maintext");
const title = ideanode.querySelector(".title");
const titleArrow = ideanode.querySelector(".title-arrow");
const mainArrow = ideanode.querySelector(".maintxt-arrow");
const comments = ideanode.querySelector(".comments");
titleArrow.addEventListener('click', function() {
maintxt.classList.toggle("hidden");
mainArrow.classList.toggle("hidden");
if (comments.classList.contains("hidden")) {;
} else {
comments.classList.toggle("hidden");
};
});
mainArrow.addEventListener("click", function() {
comments.classList.toggle("hidden");
});
});
You have a couple of options here, but the thing they have in common is that when you get a click on a .title-arrow element, you know which .title-arrow was clicked because it's the value of this (and event.currentTarget) in the event callback. From there, you can find the other elements it relates to using various DOM properties and methods, such as closest or the element version of querySelector.
So you could loop through all the .title-arrow elements and hook click on them, and then work it out from there. But I think you probably want to use event delegation instead: Hook click once, on the container for the various .ideanode elements, and then use event.target to figure out what to do.
I assume all those .ideanode elements are in a container, e.g. something like:
<div class="container">
<div class="ideanode">
<div class="ideanodeheader">Need</div>
<div class="content">
<div class="title">
<h3 contenteditable="True" onclick='this.focus();'>Title</h3>
</div>
<i class="fas fa-sort-down title-arrow">v</i>
<div class="maintext">
<textarea placeholder="Text" class="maintextinput"></textarea>
</div>
<i class="fas fa-sort-down maintxt-arrow">v</i>
<div class="comments">
<textarea placeholder="Comments" class="commentsinput"></textarea>
</div>
</div>
</div>
<div class="ideanode">
<div class="ideanodeheader">Need</div>
<div class="content">
<div class="title">
<h3 contenteditable="True" onclick='this.focus();'>Title</h3>
</div>
<i class="fas fa-sort-down title-arrow">v</i>
<div class="maintext">
<textarea placeholder="Text" class="maintextinput"></textarea>
</div>
<i class="fas fa-sort-down maintxt-arrow">v</i>
<div class="comments">
<textarea placeholder="Comments" class="commentsinput"></textarea>
</div>
</div>
</div>
<!-- ...and so on... -->
</div>
So you can do this (see comments):
// A single handler on the container
document.querySelector(".container").addEventListener("click", function(event) {
// Find the arrow that was clicked and the .ideanode it's in, if any
const arrow = event.target.closest(".title-arrow, .maintxt-arrow");
const ideanode = arrow && arrow.closest(".ideanode");
if (!ideanode || !this.contains(ideanode)) {
// Click wasn't on a `.title-arrow` or a `.maintxt-arrow` within an `.ideanode`
return;
}
if (arrow.matches(".title-arrow")) {
// It was a .title-arrow
titleArrowClick.call(arrow, ideanode, event);
} else {
// It was a .maintxt-arrow
mainArrowClick.call(arrow, ideanode, event);
}
});
function titleArrowClick(ideanode, event) {
// Use `querySelector` to look for elements within `.ideanode`
ideanode.querySelector(".maintext").classList.toggle("hidden");
ideanode.querySelector(".maintxt-arrow").classList.toggle("hidden");
const comments = ideanode.querySelector(".comments");
// (Couldn't the following be replaced with `comments.classList.add("hidden");` ?)
if (comments.classList.contains("hidden")){
;
} else {
comments.classList.toggle("hidden");
};
}
function mainArrowClick(ideanode, event) {
ideanode.querySelector(".comments").classList.toggle("hidden");
}
Live Example:
// A single handler on the container
document.querySelector(".container").addEventListener("click", function(event) {
// Find the arrow that was clicked and the .ideanode it's in, if any
const arrow = event.target.closest(".title-arrow, .maintxt-arrow");
const ideanode = arrow && arrow.closest(".ideanode");
if (!ideanode || !this.contains(ideanode)) {
// Click wasn't on a `.title-arrow` or a `.maintxt-arrow` within an `.ideanode`
return;
}
if (arrow.matches(".title-arrow")) {
// It was a .title-arrow
titleArrowClick.call(arrow, ideanode, event);
} else {
// It was a .maintxt-arrow
mainArrowClick.call(arrow, ideanode, event);
}
});
function titleArrowClick(ideanode, event) {
// Use `querySelector` to look for elements within `.ideanode`
ideanode.querySelector(".maintext").classList.toggle("hidden");
ideanode.querySelector(".maintxt-arrow").classList.toggle("hidden");
const comments = ideanode.querySelector(".comments");
// (Couldn't the following be replaced with `comments.classList.add("hidden");` ?)
if (comments.classList.contains("hidden")){
;
} else {
comments.classList.toggle("hidden");
};
}
function mainArrowClick(ideanode, event) {
ideanode.querySelector(".comments").classList.toggle("hidden");
}
.hidden {
display: none;
}
<div class="container">
<div class="ideanode">
<div class="ideanodeheader">Need</div>
<div class="content">
<div class="title">
<h3 contenteditable="True" onclick='this.focus();'>Title</h3>
</div>
<i class="fas fa-sort-down title-arrow">v</i>
<div class="maintext">
<textarea placeholder="Text" class="maintextinput"></textarea>
</div>
<i class="fas fa-sort-down maintxt-arrow">v</i>
<div class="comments">
<textarea placeholder="Comments" class="commentsinput"></textarea>
</div>
</div>
</div>
<div class="ideanode">
<div class="ideanodeheader">Need</div>
<div class="content">
<div class="title">
<h3 contenteditable="True" onclick='this.focus();'>Title</h3>
</div>
<i class="fas fa-sort-down title-arrow">v</i>
<div class="maintext">
<textarea placeholder="Text" class="maintextinput"></textarea>
</div>
<i class="fas fa-sort-down maintxt-arrow">v</i>
<div class="comments">
<textarea placeholder="Comments" class="commentsinput"></textarea>
</div>
</div>
</div>
<!-- ...and so on... -->
</div>
Here's a suggestion, out of the many possibilities to tackle such a thing:
You start with the most basic array of classnames references and build you way into an Object with keys & values which values represent DOM nodes.
For the events part, you should very much use event-delegation so you won't need to bind an event for each and every card. Just make sure they have the same parent node, and bind your events there.
// preparation
var elms = ['maintext', 'title-arrow', 'maintxt-arrow'].reduce((acc, name) => {
acc[name] = document.querySelector(`.${name}`)
return acc
}, {}
)
// iterating each "variable"
for( let elm in elms )
console.log(elm)
<div class='maintext'></div>
<div class='title-arrow'></div>
<div class='maintxt-arrow'></div>

How to display all the documents from firestore to html

db.collection('Buses').get().then((snapshot) = > {
snapshot.forEach((busDatas) = > {
busData = busDatas.data()
console.log(busData)
document.getElementById('bus-container-dynamic').innerHTML = `
<div class="single-room-area d-flex align-items-center
mb-50 wow fadeInUp" data-wow-delay="100ms">
<div class="room-thumbnail">
<img src="${busData.ImageLink}" alt="">
</div>
<div class="room-content">
<h2>${busData.TourName}</h2>
<h6>${busData.From} to ${busData.To}</h6>
<h4>₹ ${busData.SeatPrice} </h4>
<div class="room-feature">
<h6>Boarding Point <span>${busData.BoardingTime}</span></h6>
<h6>Dropping Point <span>${busData.DroppingTime}</span></h6>
<h6>Seats Left <span>${busData.SeatsLeft}</span></h6>
<h6>Total Time <span>${busData.TotalTime}</span></h6>
</div>
<a href="#" class="btn view-detail-btn">
View Details
<i class="fa fa-long-arrow-right" aria-hidden="true"></i>
</a>
</div>
</div>`
})})
I am using this code to display my code in html but the only one document is showing on the webpage , but when i print that data in console i am getting all the documents
Do not overwrite the contents of the element on each iteration, append to them.
In fact, use a variable to append to, then assign that to the element, so you only have to manipulate the DOM once.
This line:
document.getElementById('bus-container-dynamic').innerHTML = `...`;
Keeps re-writing the whole contents of #bus-container-dynamic at each iteration.
You could instead store all the data in one variable, then assign that to the element.
A short snippet to illustrate the solution.
const myData = [1,2,3,4,5];
// Create a variable here
let html = '';
myData.forEach( e => {
// Create your element's HTML inside the loop
html += e;
});
// Then assign it to the element
document.getElementById('my-element').innerHTML = html;
<div id="my-element"></div>
And this is how I would modify the code that you posted originally.
db.collection('Buses').get().then((snapshot) = > {
let html = '';
snapshot.forEach((busDatas) = > {
busData = busDatas.data()
console.log(busData)
html += `
<div class="single-room-area d-flex align-items-center
mb-50 wow fadeInUp" data-wow-delay="100ms">
<div class="room-thumbnail">
<img src="${busData.ImageLink}" alt="">
</div>
<div class="room-content">
<h2>${busData.TourName}</h2>
<h6>${busData.From} to ${busData.To}</h6>
<h4>₹ ${busData.SeatPrice} </h4>
<div class="room-feature">
<h6>Boarding Point <span>${busData.BoardingTime}</span></h6>
<h6>Dropping Point <span>${busData.DroppingTime}</span></h6>
<h6>Seats Left <span>${busData.SeatsLeft}</span></h6>
<h6>Total Time <span>${busData.TotalTime}</span></h6>
</div>
<a href="#" class="btn view-detail-btn">
View Details
<i class="fa fa-long-arrow-right" aria-hidden="true"></i>
</a>
</div>
</div>`
document.getElementById('bus-container-dynamic').innerHTML = html;
}) // End foreach
}) // End then

Categories

Resources