I'm making a ticket bot where a user creates a ticket and then gets the support they need then after an admin or the same user closes the ticket a transcript will be saved and sent in the same channel and I've already done that but the only thing I'm struggling at is displaying Embeds and Images in that transcript log. Now it looks like this (Copy paste it to see):
file:///G:/BotTickets/Akeoe%20792817221239832627.html
I figured maybe the image would help you understand more, all the bots( ASOG ) messages is Embeds and it looks like that with images too
Code of how I save and display:
let messageCollection = new Discord.Collection();
let channelMessages = await channel.messages.fetch({
limit: 100
}).catch(err => console.log(err));
messageCollection = messageCollection.concat(channelMessages);
while(channelMessages.size === 100)
{
let lastMessageId = channelMessages.lastKey();
channelMessages = await channel.messages.fetch()({ limit: 100, before: lastMessageId }).catch(err => console.log(err));
if(channelMessages)
messageCollection = messageCollection.concat(channelMessages);
}
let msgs = messageCollection.array().reverse();
let data = await fs.readFile('./commands/template.html', 'utf8').catch(err => console.log(err));
if(data)
{
await fs.writeFile(`G:\BotTickets/${ticketUserusername + ` ` + channel.id}.html`, data).catch(err => console.log(err));
let guildElement = document.createElement('div');
let guildText = document.createTextNode(message.guild.name);
let guildImg = document.createElement('img');
guildImg.setAttribute('src', message.guild.iconURL());
guildImg.setAttribute('width', '150');
guildElement.appendChild(guildImg);
guildElement.appendChild(guildText);
console.log(guildElement.outerHTML);
await fs.appendFile(`G:\BotTickets/${ticketUserusername + ` ` + channel.id}.html`,
guildElement.outerHTML).catch(err => console.log(err));
msgs.forEach(async msg => {
let parentContainer = document.createElement("div");
parentContainer.className = "parent-container";
let avatarDiv = document.createElement("div");
avatarDiv.className = "avatar-container";
let img = document.createElement('img');
img.setAttribute('src', msg.author.displayAvatarURL());
img.className = "avatar";
avatarDiv.appendChild(img);
parentContainer.appendChild(avatarDiv);
let messageContainer = document.createElement('div');
messageContainer.className = "message-container";
let nameElement = document.createElement("span");
let name = document.createTextNode(msg.author.tag + " " + msg.createdAt.toDateString() + " " +
msg.createdAt.toLocaleTimeString() + " EST");
nameElement.appendChild(name);
messageContainer.append(nameElement);
if(msg.content.startsWith("```"))
{
let m = msg.content.replace(/```/g, "");
let codeNode = document.createElement("code");
let textNode = document.createTextNode(m);
codeNode.appendChild(textNode);
messageContainer.appendChild(codeNode);
}
else
{
let msgNode = document.createElement('span');
let textNode = document.createTextNode(msg.content);
msgNode.append(textNode);
messageContainer.appendChild(msgNode);
}
parentContainer.appendChild(messageContainer);
await fs.appendFile(`G:\BotTickets/${ticketUserusername + ` ` + channel.id}.html`,
parentContainer.outerHTML).catch(err => console.log(err));
});
}
Related
No matter what I do, I'm unable to display my data. In my HTML I've set up this empty list:
<div class="reviews" style="margin-top: 40px;">
<ul id="reviews-list"></ul>
</div>
And this is what I have for JS:
// load
const querySnapshot = await getDocs(collection(db, "reviews"));
querySnapshot.forEach((doc) => {
createFormData(doc);
})
const formData = document.querySelector('.reviews');
function createFormData(doc) {
let div = document.createElement('DIV');
let title = document.createElement('span');
let hall = document.createElement('span');
let content = document.createElement('span');
title.textContent = doc.data().title;
hall.textContent = doc.data().hall;
content.textContent = doc.data().content;
div.appendChild(title);
div.appendChild(hall);
div.appendChild(content);
formData.appendChild(div);
}
Can anyone help?
I tried multiple Youtube videos and other sources to display my database data in a ul, and it either gives errors or nothing happens.
try this
const formData = document.querySelector('.reviews');
createFormData()
async function createFormData() {
const querySnapshot = await getDocs(collection(db, "reviews"));
querySnapshot.forEach((doc) => {
const div = document.createElement('DIV');
const title = document.createElement('span');
const hall = document.createElement('span');
const content = document.createElement('span');
title.textContent = doc.data().title;
hall.textContent = doc.data().hall;
content.textContent = doc.data().content;
div.appendChild(title);
div.appendChild(hall);
div.appendChild(content);
formData.appendChild(div);
})
}
Repo: https://github.com/bigolboyyo/weatherdbapp
Hello! I am working on a small project working with an API for the first time. I'm making a simple weather app that allows you to type in a location and append a "card" of data.
This card has a "front" and "back". Front being the weather data and the back being a simple textarea notepad.
As far as functionality goes I am just about there. My only issue is now when I have more than one card I only get an event listener on the first card button and the first card's button affects all the other cards created after! How would I apply the event listener for each card's buttons made and have those buttons only affect the relevant card?
Current code I'm working with
let notesBtn = document.getElementById("notes-btn");
notesBtn.addEventListener("click", handleFrontClick);
console.log(notesBtn);
function handleFrontClick(e) {
e.target.parentNode.remove();
card.appendChild(back);
let frontBtn = document.getElementById("front-btn");
frontBtn.addEventListener("click", (e) => {
e.target.parentNode.remove();
card.appendChild(front);
});
ALL JS (git repo above)
const body = document.getElementsByTagName("body");
const unsplashRandom =
"https://source.unsplash.com/random/1920x1080/?landscapes";
document.body.style.backgroundImage = `url(${unsplashRandom})`;
const header = document.createElement("div");
header.className = "header";
header.id = "header";
document.body.append(header);
const container = document.createElement("div");
container.className = "container";
document.body.append(container);
const h1 = document.createElement("h1");
h1.id = "h1";
h1.textContent = "WeatherDB Search";
h1.style.textAlign = "center";
header.append(h1);
let p1 = document.createElement("p");
p1.id = "p1";
p1.textContent = "Enter location for today's weather!";
p1.style.textAlign = "center";
header.append(p1);
const cityInput = document.createElement("input");
cityInput.className = "search-inputs";
cityInput.id = "city-input";
cityInput.placeholder = " ex: New York, Toronto, London";
header.append(cityInput);
const searchButton = document.createElement("button");
searchButton.className = "buttons";
searchButton.id = "search-btn";
searchButton.textContent = "🔍";
let br = document.createElement("br");
header.append(br);
header.append(searchButton);
function fetchWeather(e) {
let userInput = cityInput.value;
let config = {
Headers: {
"Content-type": "application/json",
},
};
return fetch(
`https://weatherdbi.herokuapp.com/data/weather/${userInput}`,
config
)
.then((res) => res.json())
.then((json) => weatherSearch(json, userInput))
.catch((err) => {
window.alert(
`${err} \n https://weatherdbi.herokuapp.com/data/weather/${userInput}`
);
console.log(err);
});
}
function weatherSearch(e, userInput) {
cityInput.value = "";
let weatherKeys = Object.keys(e.currentConditions);
let weatherValues = Object.values(e.currentConditions);
let temps = Object.values(weatherValues[1]);
let speeds = Object.values(weatherValues[4]);
const card = document.createElement("div");
card.id = `${userInput}-card`;
card.className = "cards";
container.append(card);
const front = document.createElement("div");
front.id = `${userInput}-front`;
front.className = "front";
front.innerHTML = `
<h1>${userInput.toUpperCase()}</h1>
<p>Time: ${weatherValues[0]}</p>
<li id="comment">Comment: ${weatherValues[6]}</li>
<li id="precipitation">Precipitation: ${weatherValues[2]}
<li id="temp">Temp: ${temps[0]}c | ${temps[1]}f</li>
<li id="humidity">Humidity: ${weatherValues[3]}</li>
<li id="wind">Wind Speed: ${speeds[0]}km | ${speeds[1]}mile</li>
</br>
<button id="notes-btn" class="buttons">Notes</button>
`;
card.append(front);
const back = document.createElement("div");
back.id = `${userInput}-back`;
back.className = "back";
back.innerHTML = `
<textarea id="back-text" name="backtext"
rows="25" placeholder="NotePad">
</textarea>
</br>
<button id="front-btn">Flip</button>
`;
let notesBtn = document.getElementById("notes-btn");
notesBtn.addEventListener("click", handleFrontClick);
console.log(notesBtn);
function handleFrontClick(e) {
e.target.parentNode.remove();
card.appendChild(back);
let frontBtn = document.getElementById("front-btn");
frontBtn.addEventListener("click", (e) => {
e.target.parentNode.remove();
card.appendChild(front);
});
}
}
document.addEventListener("DOMContentLoaded", (e) => {
searchButton.addEventListener("click", (e) => {
fetchWeather();
});
document.addEventListener("keydown", function (e) {
if (e.key === "Enter" && cityInput.value.length > 0) {
fetchWeather();
}
});
});
I'm having trouble implementing the logic that will limit me from adding the same items to my shopping list. When the item is the same, I just want to display the quantity with the existing item.
<div class="pizzas">
</div>
<div class="shoppingCart">
<p class="totalPrice">Hungry? order our pizzas</p>
</div>
// js
fetch("https://raw.githubusercontent.com/alexsimkovich/patronage/main/api/data.json")
.then(data => data.json())
.then(data => {
let valueCurrency = 0;
data.forEach(element => {
const shoppingCart = document.querySelector(".shoppingCart");
const pizzas = document.querySelector(".pizzas");
const box = document.createElement("div");
const img = document.createElement("img");
const title = document.createElement("h3");
const ingredients = document.createElement("p");
const price = document.createElement("h4");
const btn = document.createElement("button");
const totalPrice = document.querySelector(".totalPrice");
box.className = "box";
ingredients.className = "ingredients"
btn.className = "btn";
img.src = element.image;
img.className = "img";
title.innerHTML = element.title;
ingredients.innerHTML = element.ingredients;
price.innerHTML = element.price.toFixed(2) + " zł";
btn.innerHTML = "Dodaj do koszyka";
box.appendChild(img);
box.appendChild(title);
box.appendChild(ingredients);
box.appendChild(price);
box.appendChild(btn);
pizzas.appendChild(box);
btn.addEventListener("click", (e) => {
valueCurrency = valueCurrency + element.price;
const pizza = document.createElement("div");
pizza.className = "pizzaList";
const pizzasList = document.createElement("li");
const pizzaPrice = document.createElement("p");
const btnRemove = document.createElement("button");
btnRemove.innerText = "X";
pizzasList.innerText = title.textContent;
pizzaPrice.innerText = price.textContent;
pizza.appendChild(pizzasList);
pizza.appendChild(pizzaPrice);
pizza.appendChild(btnRemove);
totalPrice.innerText = "Całkowita cena: " + valueCurrency.toFixed(2);
if(pizzasList.innerText === pizzasList.innerText)
{
// don't add another item to the list
// just add +1 to existing element
}
else
{
// add an item to the list
shoppingCart.prepend(pizza);
}
btnRemove.addEventListener("click", (e) => {
pizza.remove();
valueCurrency = valueCurrency - element.price;
totalPrice.innerText = "Całkowita cena: " + valueCurrency.toFixed(2);
})
})
});
})
.catch(err => console.log(err));
My problem is exactly in the conditional statement, I don't know exactly how to implement the counting of the same pizzas option.
Thank you in advance for your help.
Since you are using html elements for this, what you can do is to use a data-attribute in your pizza element and increment it each time you need.
Something like:
if(pizzasList === pizzasList)
{
pizza.dataset.total = Number(pizza.dataset.total) + 1;
}
else
{
pizza.dataset.total = 1;
shoppingCart.prepend(pizza);
}
Then just use pizza.dataset.total to retieve the total number of repetitions.
I'm trying to implement server side pagination with NodeJS/Express. But the frontend rendering of it isn't working as expected. I fetch from a third-party API and implement the logic for the pagination. I then connect it to the frontend for rendering.
I have created cards to render the information from the API, first time remove the cards to render next page elements/cards with the code:
if(card !== undefined){
card.remove();
}
It works and it removes the cards, you can see this in the frontend, first eventlistener. But when I try to implement the same in the second eventlistener the elements/cards aren't removed and replaced with new ones.
Pagination - Backend
const express = require('express');
const router = express.Router();
const fetch = require('node-fetch');
router.get('/pokemon', function(req, res) {
async function getPokemonInfo(){
return fetch('https://pokeapi.co/api/v2/pokemon?limit=251')
.then(response => response.json())
.then(data => {
getDetailsPokemon(data)
}).catch(error => {
console.log(error);
})
}
getPokemonInfo()
async function getDetailsPokemon(pokemon){
const pokemonArr = pokemon.results;
const eachPokemon = pokemonArr.map(pokeEl => {
return fetch(pokeEl.url)
.then(response => response.json())
.catch(error => {
console.log(error);
})
})
Promise.all(eachPokemon)
.then(values => {
const page = parseInt(req.query.page);
const limit = parseInt(req.query.limit);
console.log(page, limit);
const startIndex = (page - 1) * limit;
const endIndex = page * limit;
console.log(startIndex, endIndex);
const results = {}
if(endIndex < values.length){
results.next = {
page: page + 1,
limit: limit
}
}
if(startIndex > 0){
results.previous = {
page: page - 1,
limit: limit
}
}
results.result = values.slice(startIndex, endIndex);
console.log(results);
res.json(results)
})
}
})
module.exports = router;
Pagination - Frontend
const paginatedApp = {
paginatedPokemon: async function(){
await fetch(`http://localhost:1337/pokemon?page=1&limit=20`)
.then(response => response.json())
.then(data => {
this.createCards(data)
})
},
createCards: function(pokemonObj){
let next = document.querySelector('.next');
let previous = document.querySelector('.previous');
pokemonObj.result.map(pokeEl => {
// Variables
let main = document.querySelector('main');
let card = document.createElement('div');
let imgHolder = document.createElement('div');
let img = document.createElement('img');
let infoHolder = document.createElement('div');
let infoBoxOne = document.createElement('div');
let infoBoxTwo = document.createElement('div');
let pId = document.createElement('p');
let pName = document.createElement('p');
let boxForType = document.createElement('div');
let id = document.createTextNode('id:');
let name = document.createTextNode('name:');
let type = document.createTextNode('type:');
// Info box 1
let infoPId = document.createElement('p');
let infoPName = document.createElement('p');
let infoPType = document.createElement('p');
infoPId.append(id);
infoPName.append(name);
infoPType.append(type);
infoBoxOne.append(infoPId, infoPName, infoPType);
infoBoxTwo.append(pId, pName, boxForType);
// Lägg till klasser
card.classList.add('card');
imgHolder.classList.add('imgHolder');
infoHolder.classList.add('infoHolder');
boxForType.classList.add('boxForType');
img.classList.add('img');
infoHolder.classList.add('infoHolder');
pId.classList.add('id');
pName.classList.add('name');
infoBoxOne.classList.add('infoBoxOne');
infoBoxTwo.classList.add('infoBoxTwo');
img.src = pokeEl.sprites.other['official-artwork']['front_default'];
pId.append(`#${pokeEl.id}`);
pName.append(pokeEl.name);
// Types
pokeEl.types.map(pokeType => {
let pokemonType = pokeType.type.name
let pokes = document.createElement('p');
pokes.append(pokemonType)
boxForType.append(pokes);
})
imgHolder.appendChild(img);
card.appendChild(imgHolder)
main.appendChild(card);
infoHolder.append(infoBoxOne)
infoHolder.append(infoBoxTwo)
card.appendChild(infoHolder);
boxForType.children[0].style.border = '1px solid #fff';
boxForType.children[1] ? boxForType.children[1].style.border = '1px solid #fff' : console.log('boxForType.children[1] dosen\'t exist for this post');
next.addEventListener('click', () => {
if(card !== undefined){
card.remove();
}
})
})
// Second next eventlistener
next.addEventListener('click', () => {
fetch(`http://localhost:1337/pokemon?page=${pokemonObj.next.page++}&limit=20`)
.then(response => response.json())
.then(data => {
data.result.map(dataEl => {
let main = document.querySelector('main');
let card = document.createElement('div');
if(card !== undefined){
card.remove();
}
let imgHolder = document.createElement('div');
let img = document.createElement('img');
let infoHolder = document.createElement('div');
let infoBoxOne = document.createElement('div');
let infoBoxTwo = document.createElement('div');
let pId = document.createElement('p');
let pName = document.createElement('p');
let boxForType = document.createElement('div');
let id = document.createTextNode('id:');
let name = document.createTextNode('name:');
let type = document.createTextNode('type:');
// Info box 1
let infoPId = document.createElement('p');
let infoPName = document.createElement('p');
let infoPType = document.createElement('p');
infoPId.append(id);
infoPName.append(name);
infoPType.append(type);
infoBoxOne.append(infoPId, infoPName, infoPType);
infoBoxTwo.append(pId, pName, boxForType);
// Lägg till klasser
card.classList.add('card');
imgHolder.classList.add('imgHolder');
infoHolder.classList.add('infoHolder');
boxForType.classList.add('boxForType');
img.classList.add('img');
infoHolder.classList.add('infoHolder');
pId.classList.add('id');
pName.classList.add('name');
infoBoxOne.classList.add('infoBoxOne');
infoBoxTwo.classList.add('infoBoxTwo');
img.src = dataEl.sprites.other['official-artwork']['front_default'];
pId.append(`#${dataEl.id}`);
pName.append(dataEl.name);
// Types
dataEl.types.map(pokeType => {
let pokemonType = pokeType.type.name
let pokes = document.createElement('p');
pokes.append(pokemonType)
boxForType.append(pokes);
})
imgHolder.appendChild(img);
card.appendChild(imgHolder)
main.appendChild(card);
infoHolder.append(infoBoxOne)
infoHolder.append(infoBoxTwo)
card.appendChild(infoHolder);
if(card !== undefined){
card.remove();
}
})
})
})
}
}
paginatedApp.paginatedPokemon();
Usually my page looks like this:
Take note of the scroll bar on right most part of the image.
PROBLEM: sometimes the school logo card would appear at the bottom of the page whenever I go back and forth with Home tab and About tab buttons on the left.
There is no consistent count every time I switch between Home and About on whenever the school logo card would appear at the bottom.
it looks like this:
The school logo card would be rendered after the home carousel card
My js code:
const pageContent = document.getElementById('page-content')
handleLogoForm()
//handles form submission for school logo card
function handleLogoForm(){
var logoform = document.getElementById('logo-form')
logoform.addEventListener('submit', function(e){
e.preventDefault()
let input = document.getElementById('inputGroupFile02');
let data = new FormData();
data.append('image',input.files[0]);
var url = "/web-content/api/changelogo/"
fetch(url,{
method: "POST",
headers: {
"X-CSRFToken": csrftoken,
},
body:data
})
.then((response) => response.json())
.then(function(data){
updateLogo()
e.target.reset()
handleLogoForm.call(this);
logo = document.getElementById('logo-div')
logo.innerHTML = ""
logo.innerHTML = `<img src="${data.image}" alt="no image provided" style="max-width: 7rem; max-height: 7rem;">`
})
})
}
// Getting Home Page Contents
function getLogoCard(){
var url = "http://localhost:8000/web-content/api/changelogo/"
fetch(url)
.then((response) => response.json())
.then(function(data){
// constructing nodes
// create div card parent node
var card = document.createElement('div')
card.classList.add('card')
// cardBody child
var cardBody = document.createElement('div')
cardBody.classList.add('card-body')
var header = document.createElement('h5')
header.innerText = 'School Logo'
var label1 = document.createElement('small')
label1.innerText = 'On display: '
var image = document.createElement('img')
image.src = data[0].image
image.id = 'img'
image.classList.add('card-img-top')
image.style.maxWidth = '10rem'
image.style.maxHeight = '10rem'
var form = document.createElement('form')
form.action = '/web-content/api/changelogo/'
form.method = 'POST'
form.enctype ='multipart/form-data'
form.id ='logo-form'
form.style.display = 'inline'
var csrftokennode = document.createElement('input')
csrftokennode.type = 'hidden'
csrftokennode.value = csrftoken
var inputGroup = document.createElement('div')
inputGroup.classList.add('input-group', 'mb-3')
var imageField = document.createElement('input')
imageField.type = 'file'
imageField.name = 'image'
imageField.classList.add('form-control')
imageField.required = true
imageField.id = 'inputGroupFile02'
var uploadButton = document.createElement('button')
uploadButton.type = 'submit'
uploadButton.classList.add('input-group-text')
uploadButton.for = 'inputGroupFile02'
uploadButton.innerText = 'Upload'
var label = document.createElement('label')
label.for = 'inputGroupFile02'
label.innerText = 'Change:'
// combine elemnts together
card.append(cardBody)
cardBody.append(header)
cardBody.append(label1)
cardBody.append(image)
cardBody.append(document.createElement('br'))
cardBody.append(label)
cardBody.append(form)
form.append(csrftokennode)
form.append(imageField)
form.append(uploadButton)
pageContent.append(card)
handleLogoForm()
})
}
function getCarouselCard(){
var url = "/web-content/api/home-carousel/"
fetch(url)
.then((response) => response.json())
.then(function(data){
var carouselItems = data
// // constructing nodes
var card = document.createElement('div')
card.id = 'carousel'
card.classList.add('card')
var cardBody = document.createElement('div')
cardBody.id = 'card-body'
cardBody.classList.add('card-body')
var header = document.createElement('h5')
header.innerText = 'Home Carousel'
var onDisplay = document.createElement('small')
onDisplay.innerText = 'On display: '
var cardImage = document.createElement('img')
cardImage.classList.add('card-img-top')
cardImage.alt = '...'
cardImage.style.maxWidth = '15rem'
cardImage.style.maxHeight = '15rem'
var cardLabel = document.createElement('small')
cardLabel.innerText = ""
var cardContent = document.createElement('small')
cardContent.innerText = ""
var iconGroup = document.createElement('span')
iconGroup.style.fontSize = '20px'
var trashIconSpan = document.createElement('span')
trashIconSpan.style.color = 'red'
var trashIcon = document.createElement('i')
trashIcon.classList.add('fas', 'fa-trash-alt')
var editIconSpan = document.createElement('span')
editIconSpan.style.color = 'brown'
var editIcon = document.createElement('i')
editIcon.classList.add('far', 'fa-edit')
// construct nodes
card.append(cardBody)
cardBody.append(header)
for (var i = 0; i < data.length; i++) {
cardBody.append(onDisplay)
cardImage.src = data[i].image
cardBody.append(cardImage)
cardBody.innerHTML += '<br>'
cardBody.append(cardLabel)
cardLabel.innerText = data[i].label
cardBody.innerHTML += '<br>'
cardBody.append(cardContent)
cardContent.innerText = data[i].content
cardBody.innerHTML += '<br>'
cardBody.append(iconGroup)
iconGroup.append(trashIconSpan)
trashIconSpan.append(trashIcon)
iconGroup.append(editIconSpan)
editIconSpan.append(editIcon)
cardBody.innerHTML += `<br><hr>`
}
pageContent.append(card)
})
}
// formsssssss
// change logo
function showHomeContent(){
if ( document.getElementById("homeButton").className.match(/(?:^|\s)active(?!\S)/) ){
}else{
document.getElementById('homeButton').classList.add('active')
pageContent.innerHTML = ""
getLogoCard()
getCarouselCard()
}
if ( document.getElementById("aboutButton").className.match(/(?:^|\s)active(?!\S)/) ){
document.getElementById("aboutButton").classList.remove('active')
}
}
function showAboutContent(){
if ( document.getElementById("aboutButton").className.match(/(?:^|\s)active(?!\S)/) ){
return;
}else{
document.getElementById('aboutButton').classList.add('active')
pageContent.innerHTML = ""
pageContent.innerHTML += `
this is about content
`
}
if ( document.getElementById("homeButton").className.match(/(?:^|\s)active(?!\S)/) ){
document.getElementById("homeButton").classList.remove('active')
}
}
the functions that are hooked with Home and About button on the left are showHomeContent() and showAboutContent()
As I mentioned in the comments, you are making two fetch requests that are asynchronous and they are racing to be done first. Whoever wins the race is rendered on top.
So when you fetch the contents, use Promise All
Promise.all([getLogoCard(), getCarouselCard()]).then((values) => {
values.forEach(card => pageContent.append(card));
});
In your functions, return the fetch call, have the fetch return the element you want to append to the document
function getLogoCard() {
...
return fetch(url)
.then((response) => response.json())
.then(function(data){
...
return card;
});
}