I have an array that I am iterating over with forEach and I need to add what is output to the console in html using template strings. How can i do this?
const postCategories = arr[index].category;
const postCategory = postCategories.forEach(category => {
console.log(category.name);
});
const article = `<article class="news">
<div class="news-taxonomy">
<span>//Here I need to enter the name of the category</span>
</div>
</article>`;
.forEach returns undefined, .map will return to you a result you're after.
I'm going to assume that each category contains at least a name key...
Additionally, I'm assuming you want to insert the result of that at the end of all the iterations
const postCategories = arr[index].category;
const postCategory = postCategories.map(category => {
return `<div>${category.name}</div>`;
});
const article = `
<article class="news">
<div class="news-taxonomy">
${postCategory}
</div>
</article>
`;
Note: This is my preferred format for multiline strings using "` `.
The output would be something like this:
<article class="news">
<div class="news-taxonomy">
<div>Category 1</div>
<div>Second Category</div>
<div>Category 3</div>
</div>
</article>
You just need to inject in the body with insertAdjacentHTML.
beforeend means just before the body end tag.
const postCategories = ['one', 'two', 'three']
const postCategory = postCategories.forEach(category => {
const template = `<article class="news">
<div class="news-taxonomy">
<span>${category}</span>
</div>
</article>`
document.body.insertAdjacentHTML('beforeend', template)
});
Related
So, I am trying to pull the volume info from the JSON array from the URL provided: https://www.googleapis.com/books/v1/volumes?q=HTML5
Trying to pull author, title, images, page numbers and description.
This specific class of my HTML code I want to put the JSON data that I have mentioned above in is the 'b-card' class:
<div class="booklist">
<div class="booklist-cards">
<div class="b-card">
</div>
<div class="b-card">
</div>
<div class="b-card">
</div>
<div class="b-card">
</div>
<div class="b-card">
</div>
<div class="b-card">
</div>
<div class="b-card">
</div>
<div class="b-card">
</div>
</div>
</div>
<script src="https://www.googleapis.com/books/v1/volumes?q=HTML5"></script>
<script src="assets/js/script.js"></script>
The script.js file I have tried is below:
function handleResponse(obj) {
const book = Objects.keys(obj).map(item => obj['items']).reduce(
(acc, rec, id, array) => {
let singleBookCover = rec[id].volumeInfo.imageLinks.thumbnail;
let singleBookTitle = rec[id].volumeInfo.title;
let singleBookAuthor = rec[id].volumeInfo.authors[0];
return [...acc, {singleBookCover, singleBookTitle, singleBookAuthor}]
},
[]
).forEach( item => {
let title = document.createElement('h1');
title.textContent = `${item.singleBookTitle}`;
let author = document.createElement('strong');
author.textContent = `${item.singleBookAuthor}`;
let img = document.createElement('img');
img.src = item.singleBookCover;
img.alt = `${item.singleTitle} by ${item.singleBookAuthor}`;
let container = document.getElementsByClassName('b-card');
container.appendChild(title).appendChild(author).appendChild(img);
})
return book
}
The above code only adds the title image and author, but I cant get them to load into my HTML.
What are ways to resolve this? Am i calling the URL correctly in the HTML script tag?
Forgot to mention - would like to achieve this without using JQuery & AJAX. I have also tried inputting the callback to handleResponse in the script tag url but it doesnt work.
you can't append to the HTML because container is array so it need index of the element
container[index].appendChild(title).appendChild(author).appendChild(img);
but here simple version, and don't forget to add &callback=handleRespons to the API URL
function handleResponse(obj) {
obj.items.forEach((item, index) => {
if(index > 7) return; // limit 8 result
let div = document.createElement('div');
div.className = 'b-card';
div.innerHTML = `<h1>${item.volumeInfo.title}</h1>
<p><strong>${item.volumeInfo.authors[0]}</strong></p>
<img src="${item.volumeInfo.imageLinks.thumbnail}" alt="${item.singleTitle} by ${item.volumeInfo.authors[0]}" />`
let container = document.querySelector('.booklist-cards');
container.append(div);
})
}
<div class="booklist">
<div class="booklist-cards">
</div>
</div>
<script src="//www.googleapis.com/books/v1/volumes?q=HTML5&callback=handleResponse" async></script>
const pokemonContainer = document.getElementById('pokemonContainer');
pokemonContainer.innerHTML += `
<div>
<section class="all-comments"></section>
</div>
`;
const allComments = document.querySelector('.all-comments');
allComments.appendChild(<h1>Hello World</h1>);
<div class="row" id="pokemonContainer"></div>
I'm trying querySelector('.all-comments') but as it's in pokemonContainer that's why It's returning undefined. Someone can please guide me on how to query select something placed in innerHTML as given above?
Node.appendChild() expects a node element as parameter, you can create a text node using Document.createTextNode():
allComments.appendChild(document.createTextNode('Hello World'));
Demo:
const pokemonContainer = document.getElementById('pokemonContainer');
pokemonContainer.innerHTML += `
<div>
<section class="all-comments"></section>
</div>
`;
const allComments = document.querySelector('.all-comments');
allComments.appendChild(document.createTextNode('Hello World'));
<div class="row" id="pokemonContainer"></div>
Update: You cannot pass <h1>Hello World</h1> directly to appendChild(). First you need to create a node of the type you want, then set the text, finally pass that node to the method.
OR: You can try using Element.insertAdjacentHTML()
const pokemonContainer = document.getElementById('pokemonContainer');
pokemonContainer.innerHTML += `
<div>
<section class="all-comments"></section>
</div>
`;
const allComments = document.querySelector('.all-comments');
allComments.insertAdjacentHTML('beforeend', '<h1>Hello World</h1>');
<div class="row" id="pokemonContainer"></div>
Basically, I want to filter a list so it only shows items containing BOTH keywords inside the array.
Ex.:
searchArray = ['sys', 'config']
If the user type 'sys config', should only show "System configuration" and hide other items.
So far I came up with this, but it's not working properly, cause it shows items that contains one of the words and not both.
var searchArray = search.split(" ");
for(x in searchArray){
filteredMenu = $('.texto:contains(\'' + searchArray[x] + '\')')
}
Check that .every one of the keywords is included:
const texts = [...$('.texto')]
.filter(element => searchArray.every(
substr => element.textContent.includes(substr)
));
Demo:
searchArray = ['sys', 'config']
const texts = [...$('.texto')]
.filter(element => searchArray.every(
substr => element.textContent.includes(substr)
));
for (const text of texts) {
console.log(text);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="texto">
foo
</div>
<div class="texto">
config
</div>
<div class="texto">
sys config
</div>
<div class="texto">
system configuration
</div>
<div class="texto">
sys
</div>
<div class="texto">
bar
</div>
Also, in some cases it is useful to construct a regular expression ("regex") string, and to use this to perform the search.
I used the solution posted by a guy in Brazillian SO. Adding multiple :contains seems to work perfectly. Also, the answer from CertainPerformance works great!
var arrayBusca = ["config", "empresa"];
var stringBusca = '';
arrayBusca.forEach((item) => stringBusca = stringBusca.concat(`:contains("${item}")`));
console.log(stringBusca); // output: :contains("config"):contains("empresa")
So, i got everything almost working as i want it, just a mistake that im struggling. Everytime i search for an item, when the result for that item shows the length is repeated.
When i search for ox there are 2 results and that is correct, but the length (2) shows in both of them, i only display one
[Code]
const resultHtml = (itemsMatch) => {
if (itemsMatch.length > 0) {
const html = itemsMatch
.map(
(item) => `
<span>${itemsMatch.length}</span>
<div class="card">
<div class="items-img">
</div>
<div class="items-info">
<h4>${item.title}</h4>
<small>${item.path}</small>
</div>
</div>
`
)
.join('');
//console.log(html);
itemList.innerHTML = html;
}
};
////
Question 2
I got one more question, i was trying to get the image from the Json and what i got was the path haha
why the apth and not the img
const resultHtml = (itemsMatch) => {
if (itemsMatch.length > 0) {
const html =
`<span class="items-results">${itemsMatch.length} Resultados</span>` +
itemsMatch
.map(
(item) => `
<div class="card">
<div class="items-img">
${item.image}
</div>
<div class="items-info">
<h4>${item.title}</h4>
<small>${item.path}</small>
</div>
</div>
`
)
.join('');
console.log(html);
itemList.innerHTML = html;
}
};
If you move <span>${itemsMatch.length}</span> out of your map callback, it will not repeat for each item. Read more about map() here.
Replace:
const html = itemsMatch
.map(
(item) => `
<span>${itemsMatch.length}</span>
... more HTML here
`
)
.join('');
With this:
const html = `<span>${itemsMatch.length}</span>` + (
itemsMatch
.map(
(item) => `
<div class="card">
<div class="items-img">
</div>
<div class="items-info">
<h4>${item.title}</h4>
<small>${item.path}</small>
</div>
</div>
`
)
.join('')
);
Regarding your image issue:
You are just outputting the path and that's why it's printing out just the path. If you are trying to display an image then put the path as source of <img> tag.
So, instead of just:
${item.image}
Use:
<img src="${item.image}">
I am working with cheerio and I am stuck at a point where I want to get the href value of children div of <div class="card">.
<div class="Card">
<div class="title">
<a target="_blank" href="test">
Php </a>
</div>
<div>some content</div>
<div>some content</div>
<div>some content</div>
</div>
I got first childern correctly but i want to get div class=title childern a href value. I am new to node and i already search for that but i didn't get an appropriate answer.
var jobs = $("div.jobsearch-SerpJobCard",html);
here is my script
const rp = require('request-promise');
const $ = require('cheerio');
const potusParse = require('./potusParser');
const url = "";
rp(url)
.then((html)=>{
const Urls = [];
var jobs = $("div.Card",html);
for (let i = 2; i < jobs.length; i++) {
Urls.push(
$("div.Card > div[class='title'] >a", html)[i].attribs.href
);
}
console.log(Urls);
})
.catch(err => console.log(err));
It looks something like this:
$('.Card').map((i, card) => {
return {
link: $(card).find('a').text(),
href: $(card).find('a').attr('href'),
}
}).get()
Edit: the nlp library is chrono-node and I also recommend timeago.js to go the opposite way