I am trying to display Unsplash images on cards.
The cards are created using JavaScript.
The 10 objects from the Unsplash API is shown on the console.
However, I cannot seem to find the problem on why the cards and the API Unsplash images are not displaying.
Appreciate any help, thanks.
const resultsNav = document.getElementById('resultsNav');
const favouritesNav = document.getElementById('favouritesNav');
const imagesContainer = document.querySelector('.images-container');
const saveConfirmed = document.querySelector('.saveConfirmed');
const loader = document.querySelector('.loader');
// Unsplash API
const count = 10;
const apiKey = 'DEMO KEY';
const apiUrl = `https://api.unsplash.com/photos/random?client_id=${apiKey}&count=${count}`;
let resultsArray = [];
function updateDOM() {
resultsArray.foreach((result) => {
// Card Container
const card = document.createElement('div');
card.classList.add('card');
// link
const link = document.createElement('a');
link.href = result.hdurl;
//Images
const image = document.createElement('img');
image.src = result.url;
image.alt = 'Image';
image.loading = 'lazy';
image.classList.add('card-img-top');
//Card Body
const cardBody = document.createElement('div');
cardBody.classList.add('card-body');
// Save Text
const saveText = document.createElement('p');
saveText.classList.add('clickable');
saveText.textContent = 'Add To Favourites';
// Append
cardBody.append(saveText);
link.appendChild(image);
card.append(link, cardBody);
imagesContainer.appendChild(card);
});
}
// Get 10 Images from Unsplash API
async function getUnplashPictures() {
try {
const response = await fetch(apiUrl);
resultsArray = await response.json();
console.log(resultsArray);
updateDOM();
} catch (error) {
// Catch Error Here
}
}
// On Load
getUnplashPictures();
Let's fix the for loop part;
foreach() usage should be with capital E as .forEach() that cause an error and your response objects prop were different named.
let resultsArray = [];
function updateDOM() {
for (let result of resultsArray) {
// Card Container
const card = document.createElement('div');
card.classList.add('card');
// link
const link = document.createElement('a');
link.href = result.links.self;
//Images
const image = document.createElement('img');
image.src = result.urls.small;
image.alt = 'Image';
image.loading = 'lazy';
image.classList.add('card-img-top');
//Card Body
const cardBody = document.createElement('div');
cardBody.classList.add('card-body');
// Save Text
const saveText = document.createElement('p');
saveText.classList.add('clickable');
saveText.textContent = 'Add To Favourites';
// Append
cardBody.append(saveText);
link.appendChild(image);
card.append(link, cardBody);
imagesContainer.appendChild(card);
};
}
Related
I'm learning javascript, hence my question might be a bit silly/simple.
Following a tutorial on Udemy, I was able to display a spreadsheet from Google Sheet in my website, using javascript to retrieve all rows contained in the document and pass them to a container in an HTML page.
This is great.
Now I would like to visualise only one row at a time, at a specific interval.
After some search I realised I can do this by using getElementById in conjunction with .innerHTML within a loop but I can't figure out what I am supposed to pass and where.
So, here is the HTML I'm using
<!DOCTYPE html>
<html><head><title>Testing Data from Sheets</title></head>
<body>
<div class="output"></div>
<script src="sheets.js"></script>
</body>
</html>
And here is the JS
const sheetID = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx';
const base = `https://docs.google.com/spreadsheets/d/${sheetID}/gviz/tq?`;
const sheetName = 'quotes';
let qu = 'Select D';
const query = encodeURIComponent(qu);
const url = `${base}&sheet=${sheetName}&tq=${query}`;
const data = [];
document.addEventListener('DOMContentLoaded', init);
const output = document.querySelector('.output');
function init() {
console.log('ready');
fetch(url)
.then(res => res.text())
.then(rep => {
//console.log(rep);
const jsData = JSON.parse(rep.substr(47).slice(0, -2));
console.log(jsData);
const colz = [];
jsData.table.cols.forEach((heading) => {
if (heading.label) {
colz.push(heading.label.toLowerCase().replace(/\s/g, ''));
}
})
jsData.table.rows.forEach((main) => {
//console.log(main);
const row = {};
colz.forEach((ele, ind) => {
//console.log(ele);
row[ele] = (main.c[ind] != null) ? main.c[ind].v : '';
})
data.push(row);
})
maker(data);
})
}
function maker(json) {
const div = document.createElement('div');
div.style.display = 'grid';
output.append(div);
let first = true;
json.forEach((el) => {
//console.log(ele);
const keys = Object.keys(el);
div.style.gridTemplateColumns = `repeat (${keys.length} ,'1fr')`;
if (first) {
first = false;
keys.forEach((heading) => {
const ele = document.createElement('div');
//ele.textContent = heading.toLocaleUpperCase();
ele.style.background = 'black';
ele.style.color = 'white';
ele.style.fontFamily = 'Helvetica';
div.append(ele);
})
}
keys.forEach((key) => {
const ele = document.createElement('div');
//ele.style.border = '1px solid #ddd';
ele.textContent = el[key];
ele.style.background = 'black';
ele.style.color = 'white';
ele.style.fontFamily = 'Helvetica';
div.append(ele);
})
console.log(keys);
})
}
Thanks heaps for helping!
I tried using the following from other messages I've found on the forum:
var i = 0; // the index of the current item to show
setInterval(function() { // setInterval makes it run repeatedly
document
.getElementById('output')
.innerHTML = jsData[i++];
if (i == jsData.length) i = 0;
}, 1000);
I have a div with a class called post, and I am iterating through a list of posts from the backend that I want to display on the front end.
My requirement is that I first want to create an empty div and append all the created elements in that div, and then finally push that div in the <div class = 'post'. But for some reason, it's giving me an error saying appendChild is not a function.
It would be great if I could convert this empty div element to look like below just through javascript. Since I want to style each of my posts and so I am wrapping them in a div.
EDIT: Below is my javascript code that I tried
for (let i = 0; i < paginatedItems.length; i++) {
let post_wrapper = document.createElement('div');
let post_element = document.querySelector('.post');
let hr = document.createElement('hr');
// Title of the blog
let title_element = document.createElement('h2')
title_element.classList.add('mt-4');
title_element.innerHTML = paginatedItems[i].title;
post_element.appendChild(title_element);
// Image of the Blog
let image_element = document.createElement('img');
image_element.classList.add('img-fluid');
image_element.classList.add('rounded');
image_element.style.width = '672'
image_element.style.height = '372'
image_element.src = paginatedItems[i].featured_image;
post_element.appendChild(image_element);
// Author Element
let author_element = document.createElement('p');
author_element.classList.add('lead');
author_element.innerHTML = 'By ';
let author_link = document.createElement('a')
author_link.innerHTML = paginatedItems[i].author.name;
author_link.href = 'google.com'
author_element.appendChild(author_link);
author_link.appendChild(hr);
post_element.appendChild(author_element);
// // Date Element
let date_element = document.createElement('p');
date_element.classList.add('item');
date_element.innerHTML = `Posted ${timeSince(paginatedItems[i].date)} ago`;
post_element.appendChild(date_element);
date_element.appendChild(hr);
// Description Element
let description_element = document.createElement('p');
description_element.classList.add('item');
description_element.innerHTML = paginatedItems[i].content.substr(0, 300) + '....';
post_element.appendChild(description_element);
// Show more button
let input_button = document.createElement('a')
input_button.classList.add('btn-primary');
input_button.classList.add('btn');
input_button.textContent = "Show more..";
input_button.addEventListener('click',
function () {
RenderPost(paginatedItems[i].ID);
}
)
console.log(post_element);
post_wrapper.appendChild(post_element);
post_element.appendChild(input_button);
}
you have to use forEach method.
here is an example:
const postsArray = [{title: 'miaw', id: 123324}, {title: 'hello', id: 983745}];
// the dom div you want to append to.
const myDiv = document.getElementById('[yourDivId]');
postsArray.forEach(post=>{
// creating the post
var div = document.createElement('div');
var title = document.createElement('h1');
var id = document.createElement('h4');
title.textContent = post.title;
id.textContent = post.id;
// appending the elements to a div
div.append(title, id);
// then appending the post to your div
myDiv.appendChild(div);
});
Getting element by id fixed it for me
here is the final working code snippet
let post_element = document.querySelector('#posts');
for (let i = 0; i < paginatedItems.length; i++) {
let post_wrapper = document.createElement('div');
let hr = document.createElement('hr');
// Title of the blog
let title_element = document.createElement('h2')
title_element.classList.add('mt-4');
title_element.innerHTML = paginatedItems[i].title;
post_wrapper.appendChild(title_element);
// Image of the Blog
let image_element = document.createElement('img');
image_element.classList.add('img-fluid');
image_element.classList.add('rounded');
image_element.style.width = '672'
image_element.style.height = '372'
image_element.src = paginatedItems[i].featured_image;
post_wrapper.appendChild(image_element);
post_element.appendChild(post_wrapper);
}
When I received help on adding a link to symbolSpan, I am now getting a link but the symbols are showing at the bottom of the page and not in the table with the rest of the data... How do I fix that?
const renderBalances = balances => {
//
binanceBalances.innerHTML = "";
//
//console.log(balances);
balances.forEach(balance => {
let balanceLi = document.createElement("li");
balanceLi.className = "list-group-item list-group-item-justify-content-center";
let balanceDiv = document.createElement("div");
balanceDiv.className = "d-flex w-100 justify-content-between";
let symbolSpan = document.createElement("span");
symbolSpan.textContent = balance.symbol;
// balanceDiv.appendChild(symbolSpan);
function createLink(linkExtension) {
const balanceDiv = document.createElement("div");
const symbolSpan = document.createElement("span");
const link = document.createElement("a");
link.setAttribute('href', `www.binance.com/en/trade/${linkExtension}`);
link.textContent = balance.symbol;
symbolSpan.appendChild(link);
balanceDiv.appendChild(symbolSpan);
document.body.appendChild(balanceDiv);
}
createLink('myparam')
this is the rest of the code for this table
let price = document.createElement("span");
price.textContent = balance.startPrice;
balanceDiv.appendChild(price);
let available = document.createElement("span");
available.textContent = balance.holdings;
balanceDiv.appendChild(available);
let onOrder = document.createElement("span");
onOrder.textContent = balance.used;
balanceDiv.appendChild(onOrder);
balanceLi.appendChild(balanceDiv);
binanceBalances.appendChild(balanceLi);
});
};
Create a span and a link html element. For the link element append the text and the href attribute.
Attach the link element to span and span to div. At last append to DOM.
Pass the additional parameter that needs to be appended to the link.
function createLink(linkExtension) {
const balanceDiv = document.createElement("div");
const symbolSpan = document.createElement("span");
const link = document.createElement("a");
link.setAttribute('href', `www.binance.com/en/trade/${linkExtension}`);
link.textContent = 'binance link';
symbolSpan.appendChild(link);
balanceDiv.appendChild(symbolSpan);
document.body.appendChild(balanceDiv);
}
createLink('myparam')
I'm trying to make a Generator where a user can insert their Battlenet Name (name) and have it output their Emblem (data.characters[2].embemBackground) plus their light level (data.characters[0].light) on the image too.
Then, I want the user to be able to use an image link, such as: http://www.test.com/image.png
And have it get updated automatically with the stats from the API, so it overwrites the image without changing the URL.
Result:
I used html2canvas capture to get the image itself from (#character2img)
I do realize this is probably not the best way to approach this.
Code:
const { Client } = require('destiny2');
const client = new Client('apiKey');
const html2canvas = require('html2canvas');
window.memberName = function(){
var pName = document.getElementById("pageheader");
var pLl = document.getElementById('LightLevel');
var pLl2 = document.getElementById('LightLevel2');
var pLl3 = document.getElementById('LightLevel3');
var gT = document.getElementById('Guardian');
var gT2 = document.getElementById('Guardian2');
var gT3 = document.getElementById('Guardian3');
var divI = document.getElementById('character1img');
var name = document.getElementById('search').value;
client.getProfile(name, '4')
.then(data => console.log(data));
client.getProfile(name, '4').then(data => {
pName.appendChild(document.createTextNode(`${data.profile.displayName}`));
// Character 1
// Emblem Image
var elem = document.createElement("img");
elem.src = `http://bungie.net${data.characters[0].embemBackground}`;
var image = document.getElementById('character1img').appendChild(elem);
// Light Level
pLl.appendChild(document.createTextNode(`♦ ${data.characters[0].light}`));
// Character 2
// Emblem Image
var elem = document.createElement("img");
elem.src = `http://bungie.net${data.characters[1].embemBackground}`;
var image2 = document.getElementById('character2img').appendChild(elem);
// Light Level
pLl2.appendChild(document.createTextNode(`♦ ${data.characters[1].light}`));
// Character 3
// Emblem Image
var elem = document.createElement("img");
elem.src = `http://bungie.net${data.characters[2].embemBackground}`;
var image2 = document.getElementById('character3img').appendChild(elem);
// Light Level
pLl3.appendChild(document.createTextNode(`♦ ${data.characters[2].light}`));
});
}
window.screenshot = function(){
html2canvas(document.querySelector("#character1img"), {allowTaint : true}).then(canvas => {
document.body.appendChild(canvas)
});
}
window.screenshot2 = function(){
html2canvas(document.querySelector("#character2img"), {allowTaint : true}).then(canvas => {
document.body.appendChild(canvas)
});
}
window.screenshot3 = function(){
html2canvas(document.querySelector("#character3img"), {allowTaint : true}).then(canvas => {
document.body.appendChild(canvas)
});
}
I have a list of cats. Each cat object has a property cat.clicks that record the number of times the cat image has been clicked. The cat image's onclick calls the method cat.clickCat.
But of course 'this' in the clickCat method refers to the image element and not the cat object which contains the property 'clicks'.
How do I display and update the number of clicks on the image?
function Cat(src, name) {
this.src = src;
this.name = name;
this.clicks = 0; //property recording no. of clicks
}
Cat.prototype.createCatItem = function() {
let catDisplay = document.createElement("div");
catDisplay.id = "catDisplay"
let catName = document.createElement("h2");
let catImg = document.createElement("img");
let catCounter = document.createElement("div");
catCounter.id = "clicker";
catName.innerHTML = this.name;
catImg.src = this.src;
catImg.onclick = this.clickCat; //call the clickCat method
catDisplay.appendChild(catName);
catDisplay.appendChild(catImg);
catDisplay.appendChild(catCounter);
return catDisplay;
}
Cat.prototype.clickCat = function() {
this.clicks += 1; //how to access the object property clicks from this method?
let clickerDiv = document.getElementById("clicker")
clickerDiv.innerHTML = ''
clickerDiv.innerHTML = 'clicks = ' + this.clicks;
}
function App() {
this.cats = [];
}
App.prototype.add = function(cat) {
this.cats.push(cat)
}
App.prototype.listCats = function() {
let container = document.getElementById("container");
let ul = document.createElement("ul");
for (let i=0; i<this.cats.length; i++){
let li = document.createElement("li");
li.innerHTML = this.cats[i].name;
li.onclick = this.displayCat;
ul.appendChild(li);
}
container.appendChild(ul);
}
App.prototype.displayCat = function() {
let container = document.getElementById("container");
let catDisplay = document.getElementById("catDisplay")
let cats = app.cats;
let chosenCat = cats.filter(cat => cat.name === this.innerHTML);
let chosenCatItem = chosenCat[0].createCatItem();
container.removeChild(catDisplay);
container.appendChild(chosenCatItem);
console.log(chosenCat);
}
App.prototype.showFirstCat = function() {
let container = document.getElementById("container");
let catDisplay = document.getElementById("catDisplay")
let firstCat = app.cats[0].createCatItem();
container.appendChild(firstCat);
}
let app = new App;
let tea = new Cat("http://placehold.it/350x150", "tea");
let snowball = new Cat("http://placehold.it/350x200", "snowball");
let triksy = new Cat("http://placehold.it/350x300", "triksy");
let vera = new Cat("http://placehold.it/350x350", "vera");
let jon = new Cat("http://placehold.it/350x400", "jon");
app.add(tea)
app.add(snowball)
app.add(triksy)
app.add(vera)
app.add(jon)
app.listCats();
app.showFirstCat();
<div id="container">
<h1>My Cat Clicker</h1>
</div>
First of all .. beware of using this ... this always refer the object currently responsible to execute the scripts in browser ... so in your case the image is responsible for executing the click event and it has no property called clicks .. and that's why clicks is NaN
A good practice is preserve this into a variable to avoid the system replacement when executing (that=this)
Cat.prototype.createCatItem = function() {
let that=this; //preserving this value
let catDisplay = document.createElement("div");
catDisplay.id = "catDisplay"
let catName = document.createElement("h2");
let catImg = document.createElement("img");
let catCounter = document.createElement("div");
catCounter.id = "clicker";
catName.innerHTML = this.name;
catImg.src = this.src;
catImg.onclick = function() {
//alert(this);
that.clicks += 1; //how to access the object property clicks from this method?
let clickerDiv = document.getElementById("clicker")
clickerDiv.innerHTML = ''
clickerDiv.innerHTML = 'clicks = ' + that.clicks;
}
catDisplay.appendChild(catName);
catDisplay.appendChild(catImg);
catDisplay.appendChild(catCounter);
return catDisplay;
}
//Cat.prototype.clickCat = function() {
// this.clicks += 1; //how to access the object property clicks from this method?
// let clickerDiv = document.getElementById("clicker")
// clickerDiv.innerHTML = ''
// clickerDiv.innerHTML = 'clicks = ' + this.clicks;
//}