Call a constant from another function - javascript

I want to be able to access the "const history" outside in the historyInfo function so I don't have to call the historyInfo() function inside the selectOption function. The main problem is that there are two addEventListeners calling the showOption function where the historyInfo function is called. I just want the buyItemPanelbtn click to call the historyInfo function.
function showbrookton(brooktonIndex){
const brookton = Brookton.find(brookton => brookton.id === brooktonIndex)
textElement.innerText = brookton.text //fill text element
titleElement.innerText = brookton.title //title element
while (optionButtonsElement.firstChild) { //removes all buttons
optionButtonsElement.removeChild(optionButtonsElement.firstChild)
}
brookton.options.forEach(option => { //option is options and the funtion is performed on each option
if(showOption(option) && (option.text)) { //
const button = document.createElement('button')
button.innerText = option.text
button.classList.add('btn')
button.addEventListener('click', () => {
selectOption(option);
})
optionButtonsElement.appendChild(button)
}
if(option.backText){ //this goes back to previous page
const backOption = option.backText;
backButton.addEventListener('click', () => showbrookton(backOption))
} //else close window
})
}
function showOption(option){
return option.requiredState == null || option.requiredState(state)
}
function selectOption(option){
const nextbrooktonId = option.nextText
const history = option.historyText;
if (nextbrooktonId == "buyItem"){
buyItemPanel();
function buyItemPanel(){
const buyItemName = option.text;
buyItemPanelName.innerText = buyItemName
buyItemPanelPrice.innerText = "Price: " + option.price
buyPanelType.innerText = option.type
historyInfo(history);
showBuyItemPanel()
}
function historyInfo(history) {
$(HistoryPanel).append("<div>" + history + "</div>");
}
buyItemPanelbtn.addEventListener('click', () => selectOption());
const Brookton = [
{
id: "Bakery",
title: "Bakery",
text: 'Choose a Location to visit.',
options: [
{
text: 'Bread',
type: 'Food',
price: '$4',
historyText: "You bought bread",
nextText: "buyItem",
}
]
}
]

Declare the history variable outside as
.
var history;
and then in the selectOption function
history = option.historyText;
Code:
var history;
function selectOption(option) {
history = option.historyText;
historyInfo(history);
return showBuyItemPanel()
}
showbrookton(nextbrooktonId)
}
function historyInfo(history) {
$(HistoryPanel).append("<div>" + history + "</div>");
}

This seems to have solved the problem. I declared Newoption globally and then set it to the parameter option inside the selectOption function. I was then able to make a const 'history' inside the historyInfo function.
var Newoption;
function showOption(option){
return option.requiredState == null || option.requiredState(state)
}
function selectOption(option){
Newoption = option;
const nextbrooktonId = option.nextText
// const history = option.historyText;
if (nextbrooktonId == "buyItem"){
buyItemPanel();
function buyItemPanel(){
const buyItemName = option.text;
buyItemPanelName.innerText = buyItemName
buyItemPanelPrice.innerText = "Price: " + option.price
buyPanelType.innerText = option.type
showBuyItemPanel()
}
function historyInfo(){
const history = Newoption.historyText;
$(HistoryPanel).append("<div>" + history + "</div>");
updateScroll();
}
// click buy button
buyItemButton.addEventListener("click", () => {
closeItemBuyWindow();
closeLocationsMenu();
historyInfo();
});

Related

JavaScript variable coming up as undefined when used within textNode

let state = {}
var Playername;
At the start of the code the var Playername is created.
if (nextTextNodeId == 60) {
var InputName = document.getElementById('name').value;
let Playername = InputName;
alert(Playername);
if (Playername == "Andrew") {
ToggleInputOff()
state = Object.assign(state, option.setState)
showTextNode(4)
return;
}
else if (Playername == "") {
state = Object.assign(state, option.setState)
showTextNode(3)
return;
}
else {
ToggleInputOff()
state = Object.assign(state, option.setState)
showTextNode(5)
return;
}
return ToggleInputOff()
}
The alert Playername displays the inputted name in the alert box correctly, however when i go to use this variable later in the project it comes up as undefined.
{
id: 5,
text: "Welcome " + Playername + " let us start the day!",
options: [
{
text: "Let's go",
nextText: 6
}
]
},
The text nodes are accessed through this function and displayed on the screen
function showTextNode(textNodeIndex) {
const textNode = textNodes.find(textNode => textNode.id === textNodeIndex)
textElement.innerText = textNode.text
while (optionButtonsElement.firstChild) {
optionButtonsElement.removeChild(optionButtonsElement.firstChild)
}
textNode.options.forEach(option => {
if (showOption(option)) {
const button = document.createElement('button')
button.innerText = option.text
button.classList.add('btn')
button.addEventListener('click', () => selectOption(option))
optionButtonsElement.appendChild(button)
}
})
}
Whenever this text node is accessed the output is
Welcome Undefined let us start the day!

Set time interval on actions JS (Await, setTimeout Or setinterval )

We have more than 30 inputs in our HTML file, (name,adresse,phone....) on diferent pages
the script in the chrome extension autocomplete all inputs one after one, in one time,
My question is how to make a function whait for the action beforr.
set the value of each input one after one but with interval of 500ms.
function setById(id,valeur ){
setTimeout(()=>{
var ev = new Event('input');
if (document.getElementById(id)) {
Elem = document.getElementById(id) ? document.getElementById(id) : null
Elem.value =valeur;
Elem.dispatchEvent(ev);
}else{
console.log('L"element ' + id + ' introuvable, pour valeur ==> '+ valeur);
}
},500);
}
///////////////////////////////////////
// immatriculation
const immatriculation = setById('immatriculation',matricule.replaceAll('-',''));
// codePostalGarage
const codePostalGarage = setById('codePostalGarage',setData__.station_cp_n);
// villeGarage
const villeGarage = setById('villeGarage',setData__.station_ville_n);
Thank you Codeurs,
Try something like this
// dummy data
const matricule = "x-x-x"
const setData__ = {
station_cp_n: "x",
station_ville_n : "y"
}
// object from your statements
const values = [
{ 'immatriculation': matricule.replaceAll('-', '') },
{ 'codePostalGarage': setData__.station_cp_n },
{ 'villeGarage': setData__.station_ville_n }
];
cnt = 0;
const setById = () => {
const ev = new Event('input');
const [id, valeur] = Object.entries(values[cnt])[0]; // destruct the element
if (document.getElementById(id)) {
Elem = document.getElementById(id) ? document.getElementById(id) : null
Elem.value = valeur;
Elem.dispatchEvent(ev);
} else {
console.log('LĀ“element ' + id + ' introuvable, pour valeur ==> ' + valeur);
}
cnt++;
if (cnt < values.length) setTimeout(setById, 500); // stop if finished
}
setById(); // start it

addEventListener function firing an increasing amount of times each click

I am trying to make a text based game based on a tutorial on Youtube. I have a div called "HistoryPanel" where I want divs to be appended containing a string from an object property "historyText" when "buyItemPanelbtn" is clicked. While I have managed to achieve this when I click the button again it will append the div twice and three times if I click again after that and so on. Can someone show me how to make it only append once each time the button is clicked?
I have included the code and the object that the code is relevant to. I haven't included the other objects because there are a lot and they are not relevant to this problem.
const textElement = document.getElementById('text');
const titleElement = document.getElementById('title');
const buyItemPanelBackground = document.getElementById('buyItemPanelBackground');
const buyItemPanel = document.getElementById('buyItemPanel');
const buyItemPanelName = document.getElementById('buyPanelName');
const buyItemPanelPrice = document.getElementById('buyPanelPrice');
const buyPanelType = document.getElementById('buyPanelType');
const buyItemPanelbtn = document.getElementById('buyItemPanelbtn');
const buyItemNevermind = document.getElementById('buyItemNevermind');
const backButton = document.getElementById('backButton');
const closeMenuButton = document.getElementById('closeMenuButton');
const optionButtonsElement = document.getElementById('option-buttons');
//home screen
const HistoryPanel = document.getElementById('HistoryPanel');
// home screen buttons
const homeScreen = document.getElementById('homeScreen');
const menuScreen = document.getElementById('menuScreen');
const homeLocationsButton = document.getElementById('homeLocationsButton');
let state = {}
function startGame() {
state = {}
showbrookton("Bakery");
}
//close locations menu
function closeLocationsMenu(){
menuScreen.style.display = "none";
homeScreen.style.display = "block";
}
//close item buy window
function closeItemBuyWindow(){
buyItemPanelBackground.style.display = "none";
}
//hide buy item window when click nevermind
buyItemNevermind.addEventListener("click", closeItemBuyWindow);
// click buy button
buyItemPanelbtn.addEventListener("click", () => {
closeItemBuyWindow();
closeLocationsMenu();
});
//display locations menu
homeLocationsButton.addEventListener("click", () => {
menuScreen.style.display = "block";
homeScreen.style.display = "none";
startGame();
});
//close locations menu
closeMenuButton.addEventListener("click", closeLocationsMenu);
// when clicking an item
function showBuyItemPanel(){
buyItemPanelBackground.style.display = "block";
}
function showbrookton(brooktonIndex){
const brookton = Brookton.find(brookton => brookton.id === brooktonIndex)
textElement.innerText = brookton.text //fill text element
titleElement.innerText = brookton.title //title element
while (optionButtonsElement.firstChild) { //removes all buttons
optionButtonsElement.removeChild(optionButtonsElement.firstChild)
}
brookton.options.forEach(option => { //option is options and the funtion is performed on each option
if(showOption(option) && (option.text)) { //
const button = document.createElement('button')
button.innerText = option.text
button.classList.add('btn')
button.addEventListener('click', () => selectOption(option))
optionButtonsElement.appendChild(button)
}
if(option.backText){ //this goes back to previous page
const backOption = option.backText;
backButton.addEventListener('click', () => showbrookton(backOption))
} //else close window
})
}
function showOption(option){
return option.requiredState == null || option.requiredState(state)
}
function selectOption(option){
const nextbrooktonId = option.nextText
const history = option.historyText
if (nextbrooktonId == "buyItem"){
const buyItemName = option.text;
buyItemPanelName.innerText = buyItemName
buyItemPanelPrice.innerText = "Price: " + option.price
buyPanelType.innerText = option.type
const history = option.historyText;
buyItemPanelbtn.addEventListener('click', () => {
$(HistoryPanel).append("<div>" + history + "</div>")
})
return showBuyItemPanel()
}
state = Object.assign(state, option.setState) //this overrides the current state with the new ones
showbrookton(nextbrooktonId)
}
const Brookton = [
{
id: "Bakery",
title: "Bakery",
text: 'Choose a Location to visit.',
options: [
{
text: 'Bread',
type: 'Food',
price: '$4',
historyText: "You bought bread",
nextText: "buyItem",
}
]
}
]

How to render list according to localStorage input.value?

I wrote a function that trigger on input and get data from API. I need to store last input.value in localStorage and then set input.value to one in localStorage on reload. Everything is fine except when I reload the page I have value that I need but I have to click space then backspace f.e. to render things. I would like to ask where should I pass the getter from localStorage so it will trigger the function on reload, but won't break the listener for input. There is full code underneath :
let country;
let cities = [];
const citiesDiv = document.getElementById("cities");
const countryPicker = document.getElementById("country-picker");
const getData = async () => {
const response = await fetch(
`https://api.openaq.org/v1/cities?country=${country}&limit=10&parameter=no2&order_by=parameter`
);
const data = await response.json();
cities = data.results;
console.log(cities);
citiesDiv.innerHTML = "";
renderCities(cities);
};
countryPicker.value = JSON.parse(localStorage.getItem("inputValue"));
countryPicker.addEventListener("input", function(e) {
if (e.target.value.toLowerCase() === "poland".toLowerCase()) {
country = "PL";
} else if (e.target.value.toLowerCase() === "spain".toLowerCase()) {
country = "ES";
} else if (e.target.value.toLowerCase() === "germany".toLowerCase()) {
country = "DE";
} else if (e.target.value.toLowerCase() === "france".toLowerCase()) {
country = "FR";
}
localStorage.setItem("inputValue", JSON.stringify(e.target.value));
getData();
});
function renderCities(cities) {
cities.forEach(function(city) {
const p = document.createElement("p");
const button = document.createElement("button");
button.classList.add("accordion");
const div = document.createElement("div");
div.classList.add("panel");
const citiesDiv = document.getElementById("cities");
button.textContent = city.city;
citiesDiv.appendChild(button);
citiesDiv.appendChild(div);
div.appendChild(p);
p.textContent = "Lorem ipsum";
});
const acc = document.getElementsByClassName("accordion");
let i;
for (i = 0; i < acc.length; i++) {
console.log(i);
acc[i].addEventListener("click", function() {
this.classList.toggle("active");
var panel = this.nextElementSibling;
if (panel.style.maxHeight) {
panel.style.maxHeight = null;
} else {
panel.style.maxHeight = panel.scrollHeight + "px";
}
});
}
}
Refactor your code in order to make the function that fetches and renders data to be reusable for two cases:
when user changes the input.
when the page is loaded.
Replace the following part
countryPicker.value = JSON.parse(localStorage.getItem("inputValue"));
countryPicker.addEventListener("input", function(e) {
if (e.target.value.toLowerCase() === "poland".toLowerCase()) {
country = "PL";
} else if (e.target.value.toLowerCase() === "spain".toLowerCase()) {
country = "ES";
} else if (e.target.value.toLowerCase() === "germany".toLowerCase()) {
country = "DE";
} else if (e.target.value.toLowerCase() === "france".toLowerCase()) {
country = "FR";
}
localStorage.setItem("inputValue", JSON.stringify(e.target.value));
getData();
});
with
countryPicker.value = JSON.parse(localStorage.getItem("inputValue"));
fetchAndRender(countryPicker.value);
countryPicker.addEventListener("input", e => fetchAndRender(e.target.value));
function fetchAndRender(value) {
if (value.toLowerCase() === "poland".toLowerCase()) {
country = "PL";
} else if (value.toLowerCase() === "spain".toLowerCase()) {
country = "ES";
} else if (value.toLowerCase() === "germany".toLowerCase()) {
country = "DE";
} else if (value.toLowerCase() === "france".toLowerCase()) {
country = "FR";
}
localStorage.setItem("inputValue", JSON.stringify(value));
getData();
}

How do I get items from localStorage and display in my UI?

This is what I have tried. It works with just a small issue. Anytime I add a new item to the localStorage it multiplies the items when displaying it until I refresh the page
const displayStorage = () => {
let values = [],
keys = Object.keys(localStorage),
i = keys.length;
while (i--) {
if (keys[i] === 'theme') continue;
values.push(JSON.parse(localStorage.getItem(keys[i])));
}
values.reverse();
return values.forEach(obj => showNotes(obj));
};
e.g let's say I have 123 stored and I want to add 4. It returns 1231234 instead of just 1234
This is the function that handles the UI display
const showNotes = ({ id, post, date }) => {
const noteSection = document.createElement('div');
noteSection.classList.add('notes-container');
const notes = document.createElement('article');
notes.classList.add('single-note');
notes.textContent = post.substring(0, 100);
const viewMore = document.createElement('a');
viewMore.classList.add('view-more');
viewMore.textContent = '...';
viewMore.setAttribute('title', 'View more');
viewMore.addEventListener('click', e => {
e.preventDefault();
if (notes.textContent.length <= 110) {
notes.textContent = post;
notes.appendChild(viewMore);
viewMore.setAttribute('title', 'View less');
} else {
notes.textContent = post.substring(0, 100);
notes.appendChild(viewMore);
viewMore.setAttribute('title', 'View more');
}
});
const noteActions = document.createElement('span');
noteActions.classList.add('note-actions');
const deleteLink = document.createElement('a');
deleteLink.textContent = 'Delete';
deleteLink.setAttribute('data-id', `${id}`);
deleteLink.addEventListener('click', deleteNote);
const notesDate = document.createElement('aside');
notesDate.classList.add('note-date');
notesDate.textContent = date;
noteActions.appendChild(deleteLink);
notes.appendChild(viewMore);
notes.appendChild(noteActions);
noteSection.appendChild(notesDate);
noteSection.appendChild(notes);
document.querySelector('.notes').appendChild(noteSection);
};
This is the function to save
notesForm.addEventListener('submit', e => {
e.preventDefault();
const save = (sid, spost, sdate) => {
const obj = { id: sid, post: spost, date: sdate };
localStorage.setItem(`${sid}`, JSON.stringify(obj));
};
save(generateId(), post.value, dateFormat());
displayStorage();
});
its a simple solution but may be useful for someone,
just clear items from UI, and again display them from localstorage, this will show the old and new items from localstorage.

Categories

Resources