I have a javascript function that grabs a dataset numeric value and appends it to an XMLhttprequest parameter. It has to run onload as the content is printed dynamically through php.
I now am trying to create a simple carousel for the elements printed and finding some difficulty chaining onload functions.
I've found creating an additional onload function for anything breaks the first onload function. What can I do here?
function userData() {
let infoWrap = document.querySelector(".agent-detail-info").dataset.id;
console.log(infoWrap);
return infoWrap;
}
window.onload = userData;
window.onload = () => {
const request = new XMLHttpRequest();
request.open(
"GET",
`url&usertolookup=${userData()}`
);
request.onload = function () {
let response = request.response;
let parsedData = JSON.parse(response);
console.log(parsedData);
let testimonials = parsedData.data.testimonials.details;
testimonials.forEach((testimonial, index) => {
const testimonialWrap = document.querySelector(".testimonials");
// Create testimonials container
let innerTestimonials = document.createElement("div");
innerTestimonials.className = "inner-testimonial-container";
testimonialWrap.appendChild(innerTestimonials);
// Create star rating container
let starWrap = document.createElement("div");
starWrap.className = "testimonial-stars";
innerTestimonials.appendChild(starWrap);
// Create Testimonial Content
let innerTestimonialParagraph = document.createElement("p");
innerTestimonials.appendChild(innerTestimonialParagraph);
// Create Testimonial Signature
let innerTestimonialSignature = document.createElement("address");
innerTestimonials.appendChild(innerTestimonialSignature);
// Loop through rating value and create elements
let rating = testimonial.rating;
for (let i = 0; i < rating; i++) {
let star = document.createElement("i");
star.className = "fa fa-star";
starWrap.appendChild(star);
}
// Insert Testimonial Content
let testimonialText = testimonial.Testimonial;
innerTestimonialParagraph.innerHTML = testimonialText;
// Insert Testimonial Signature
let signature = testimonial.Signature;
innerTestimonialSignature.innerHTML = signature;
});
};
request.send();
};
Testing Carousel (have tried alternative with event listeners rather than inline onclick and cannot access the elements printed through the response(returns undefined as the elements are printed after dom load))
let tabIndex = 1;
function nextTestimonial(n) {
testimonialSlide((tabIndex += n));
}
function currentTestimonial(n) {
testimonialSlide((tabIndex = n));
}
function testimonialSlide(n) {
let innerTestimonials = document.querySelectorAll(
".inner-testimonial-container"
);
if (n > innerTestimonials.length) {
tabIndex = 1;
}
if (n < 1) {
tabIndex = innerTestimonials.length;
}
for (let i = 0; i < innerTestimonials.length; i++) {
innerTestimonials[i].style.display = "none";
}
innerTestimonials[tabIndex - 1].style.display = "block";
}
Random attempt to chain onload functions (this breaks the response)
window.onload = () => {
const innerTestimonialsNew = document.querySelectorAll(
".inner-testimonial-container"
);
console.log(innerTestimonialsNew);
};
Related
I'm doing an operation inside my function and I want to store my JSON data with AsyncStorage and use it elsewhere, but I'm getting an error in react native
this is my code block;
onPress={() => {
press = item.id;
// console.warn(press);
ars = options;
dd = JSON.stringify(ars);
cc = JSON.parse(dd);
for (var i = 0; i < cc.length; i++) {
if (cc[i].id == press) {
// console.warn(cc[i]);
var productData = cc[i];
var stri = JSON.stringify(cc[i]);
AsyncStorage.setItem('ProductData', stri);
var abc = AsyncStorage.getItem('ProductData');
console.warn(stri);
console.warn(abc);
}
}
}}>
how can i solve that problem?
thanks.
var abc = await AsyncStorage.getItem('ProductData');
add await as it is promise that all
so whole code will look like this
onPress={async () => {
press = item.id;
// console.warn(press);
ars = options;
dd = JSON.stringify(ars);
cc = JSON.parse(dd);
for (var i = 0; i < cc.length; i++) {
if (cc[i].id == press) {
// console.warn(cc[i]);
var productData = cc[i];
var stri = JSON.stringify(cc[i]);
AsyncStorage.setItem('ProductData', stri);
var abc =await AsyncStorage.getItem('ProductData');
console.warn(stri);
console.warn(abc);
}
}
}}>
add async to function and add await
I'm having problem with loading from local storage.
Here's a part of the code
const getTerminus = () => {
let terminus;
if (localStorage.getItem("terminus") === null) {
terminus = [];
} else {
terminus = JSON.parse(localStorage.getItem("terminus"));
}
let directions;
if (localStorage.getItem("directions") === null) {
directions = [];
} else {
directions = JSON.parse(localStorage.getItem("directions"));
}
terminus.forEach(async(stop) => {
let API_URL =
"https://ckan.multimediagdansk.pl/dataset/c24aa637-3619-4dc2-a171-a23eec8f2172/resource/d3e96eb6-25ad-4d6c-8651-b1eb39155945/download/stopsingdansk.json";
let response = await fetch(API_URL);
let data = await response.json();
const {
stops,
stopId,
stopName,
stopCode,
zoneId
} = data;
let input = stop;
let ID;
let dataArr = [];
for (let i = 0; i < stops.length; i++) {
if (
stops[i].stopName === input &&
stops[i].stopCode === directions[terminus.indexOf(input)] &&
stops[i].zoneId === 1
) {
ID = stops[i].stopId;
dataArr = [ID, stops[i].stopName];
}
}
API_URL = `https://ckan2.multimediagdansk.pl/delays?stopId=${ID}`;
response = await fetch(API_URL);
data = await response.json();
const {
delay,
estimatedTime,
routeId,
headsign
} = data;
let times = [];
let routeIds = [];
let headsigns = [];
for (let i = 0; i < delay.length; i++) {
times.push(delay[i].estimatedTime);
routeIds.push(delay[i].routeId);
headsigns.push(delay[i].headsign);
}
routeIds.push(" ");
times.push(" ");
const cardDiv = document.createElement("div");
cardDiv.classList.add("card");
const stopNameDiv = document.createElement("div");
stopNameDiv.classList.add("stop-name-div");
cardDiv.appendChild(stopNameDiv);
const stopNameSpan = document.createElement("span");
stopNameSpan.innerText = dataArr[1];
stopNameSpan.classList.add("stop-name-span");
stopNameDiv.appendChild(stopNameSpan);
const scheduleDiv = document.createElement("div");
scheduleDiv.classList.add("schedule-div");
cardDiv.appendChild(scheduleDiv);
if (headsigns.length !== 0) {
routeIds.unshift("Line");
headsigns.unshift("Direction");
times.unshift("Departure");
}
const lineSpan = document.createElement("span");
lineSpan.innerText = routeIds.join("\n");
lineSpan.classList.add("line-span");
scheduleDiv.appendChild(lineSpan);
const dirSpan = document.createElement("span");
dirSpan.innerText = headsigns.join("\n");
dirSpan.classList.add("dir-span");
scheduleDiv.appendChild(dirSpan);
const timeSpan = document.createElement("span");
timeSpan.innerText = times.join("\n");
timeSpan.classList.add("time-span");
scheduleDiv.appendChild(timeSpan);
const buttonsDiv = document.createElement("div");
buttonsDiv.classList.add("buttons-div");
cardDiv.appendChild(buttonsDiv);
const deleteButton = document.createElement("button");
deleteButton.innerHTML = '<i class="fas fa-trash"></i>';
deleteButton.classList.add("delete-button");
buttonsDiv.appendChild(deleteButton);
const dirButton = document.createElement("button");
dirButton.innerHTML = '<i class="fas fa-retweet"></i>';
dirButton.classList.add("reverse-button");
buttonsDiv.appendChild(dirButton);
stopList.appendChild(cardDiv);
});
};
document.addEventListener("DOMContentLoaded", getTerminus);
Terminus contains stop names, and directions contains direction codes.
On refresh, it fetches data from API based on stop name and direction, and displays a card with departure time etc.
The problem is, on closing and re-opening the page cards are sometimes displayed in a wrong order. I have found out, that as time between closing and opening lengthens, the probability of this occurring gets higher. After simple refresh everything is in correct order.
Does it have something to do with browser cache? Has anyone had similar issue or knows what's going on?
Alright, as #Yoshi stated, it was insequential promise error. I managed to fix it by using reduce().
Here are the threads that helped me
Resolve promises one after another (i.e. in sequence)?
Why Using reduce() to Sequentially Resolve Promises Works
I want my filters variable to update, my guess is it's re-initializing as the set value every time the function is called, whenever i try to declare it outside of the function I get a lexical error, how can I make sure it keeps the value assigned to it after a button has clicked
export function categoryRender(){
let filter = 'RICK'
console.log(filter)
const all = document.getElementById('all');
all.onclick = function(){
filter = 'ALL'
render(filter);
}
categories = categories.sort();
const filterContainer = document.getElementById("filter-container");
filterContainer.innerHTML = "";
const allFilterImg = document.getElementById('all-image');
if (filter === 'ALL'){
allFilterImg.setAttribute('src', './images/checked.jpeg')
}else{
allFilterImg.setAttribute('src', './images/unchecked.png')
console.log('unchecked all firing')
}
for (let i = 0; i < categories.length; i++){
const line = document.createElement("span");
const filterButton = document.createElement("img");
const filterLabel = document.createElement("h2");
filterContainer.appendChild(line);
line.appendChild(filterButton);
line.appendChild(filterLabel);
line.setAttribute('id', categories[i]);
line.classList.add('filter-line');
filterLabel.innerHTML = categories[i];
if (filter === categories[i]){
filterButton.setAttribute('src', './images/checked.jpeg')
}else{
filterButton.setAttribute('src', './images/unchecked.png')
}
line.onclick = function(){
filter = categories[i];
render(filter)
}
}
}
I'm very new to javascript/dev so I hope there is a an obvious solution that I've not thought of. My code returns search items from TVMaze.com API. The feature giving me trouble is the incremental search (as a user types in input box, the code returns and displays images by creating a new div and appending images, removing and replacing the an div).
My problem is that on deleting all characters from input box, I receive the error: "Uncaught (in promise) TypeError: shows is not iterable" which I suppose means that there is no object to iterate over? Thanks in advance for any help.
const input = document.querySelector("#query");
input.addEventListener("input", async function (e) {
e.preventDefault();
const searchTerm = e.target.value;
const config = { params: { q: searchTerm } };
const res = await axios.get(`http://api.tvmaze.com/search/shows?`, config);
makeImages(res.data);
clearList();
});
const makeImages = (shows) => {
const div = document.createElement("div");
for (let result of shows) {
if (result.show.image) {
const img = document.createElement("IMG");
img.className += "resultImage";
img.src = result.show.image.medium;
const title = document.createElement("h3");
title.className += "resultTitle";
title.innerText = result.show.name;
const year = document.createElement("h4");
year.className += "score";
year.innerText = result.show.premiered;
var sub = year.innerText.substring(0, 4);
var yearNum = parseInt(sub);
div.append(year);
div.append(img);
div.append(title);
document.body.appendChild(div);
}
if (yearNum <= 2000) {
var retro = document.createElement("h5");
retro.className = "retro";
retro.innerText = "retro";
div.append(retro);
}
}
};
let clearList = () => {
var allImg = document.querySelectorAll("IMG");
if (allImg.length === 0) {
document.createElement("div");
return makeImages();
}
var oldDiv = document.querySelector("div");
oldDiv.remove();
console.log(oldDiv);
};
I am trying to convert an HTML Collection of "li"s into an array, but the result in the array being emptied.
I read this question and applied that, but it doesn't work.How do I convert a HTMLCollection into an array, without emptying it?
<body>
<ul id="base"></ul>
<script>
const json = [{
"id" : "1",
"date" : "2013/05/05",
},{
"id" : "2",
"date" : "2019/05/05",
}];
for (item of json) {
const list = document.createElement('li');
list.textContent = `${item.date}`;
base.appendChild(list)
}
///the code above works fine.
const base = document.getElementById("base");
const myNodeList = base.getElementsByTagName("li");
console.log(myNodeList);
// gives HTMLCollection
const myArray = Array.from(myNodeList)
// returns empty array
</script>
</body>
the result
I tested the same code on console and it worked fine as below.
The code cannot work before you are using base before initializing it. Placing the initialization before using it makes it work.
Here I modified it: https://jsfiddle.net/tk78z5gq/
Thank you so much guys!
The problem was async.
I should have said that earlier, I fetch the data from NeDB with async function.
The array was empty because DOM was executed before async function fetching data was executed.
The full code below was fixed one. I'm not sure this is best way, but at least it worked.
let dataM = null;
async function getHTMLData() {
const response = await fetch('/api');
const data = await response.json();
dataM = data;
const base = document.getElementById("base");
for (item of data) {
const root = document.createElement('li');
root.className = "col-md-auto";
root.title = `${item.date}`;
const border = document.createElement('div');
border.className = "row no-gutters border rounded overflow-hidden flex-md-row mb-4 shadow-sm h-md-250 position-relative";
root.appendChild(border);
const flex = document.createElement('div');
flex.className = "col p-4 d-flex flex-column position-static";
border.appendChild(flex);
const country = document.createElement('strong');
country.className = "d-inline-block mb-2 text-primary";
const title = document.createElement('h3');
title.className = "mb-0";
const date = document.createElement('div');
date.className = "mb-1 text-muted";
date.id = "date";
const fieldItem = document.createElement('p');
fieldItem.className = "mb-auto";
const imageRoot = document.createElement('figure');
imageRoot.className = "image mb-2";
const link = document.createElement('a');
link.className = "p-4";
const linkText = document.createTextNode("Source");
country.textContent = `${item.country}`;
title.textContent = `${item.title}`;
date.textContent = `${item.date}`;
fieldItem.textContent = `${(item.fieldItem)}`;
for (var i = 0; i < item.imageSrc.length; i++) {
const image = document.createElement('img');
image.src = item.imageSrc[i];
image.alt = 'seized items'
image.className = "w-5 h-5";
// image.crossOrigin ="use-credentials";
imageRoot.appendChild(image);
}
const imageText = document.createElement('text');
imageText.innerHTML = `<br>${item.imageText}`;
imageRoot.appendChild(imageText);
link.appendChild(linkText);
link.title = "Source";
link.href = item.URL;
link.className = "";
flex.append(country, title, date, fieldItem, imageRoot, link);
base.appendChild(root);
}
}
sortDate();
async function sortDate() {
const gethtml = await getHTMLData();
const base = await document.getElementById("base");
const myNodeList = await base.getElementsByTagName("li");
const myArray = Array.from(myNodeList);
myArray.sort(function (a, b) {
return new Date(a.title) > new Date(b.title)? -1
: new Date(a.title) < new Date(b.title)? 1
: 0;
})
for (i = 0; i < myArray.length; i++) {
base.appendChild(base.removeChild(myArray[i]))}
}
index.js
app.get('/api', (request, response) => {
database.find({}).exec(function(err, data){
if (err) {
response.end();
return;
}
response.json(data);
})
});