I have an array of objects which all follow the same format and another array of objects
Using the following code, I am able to generate the subheadings with no issues. However what I would like to have is subheadings separating the generated services. The subheadings separations are based on the services[k].category.
This is what I have so far, however it is not working. The subheadings generate without issue, however the rest is not working:
let categories = [{
name: "Logo and Branding"
},
{
name: "Web Design"
},
{
name: "Print"
},
{
name: "Presentations"
},
{
name: "Art & Illustration"
},
{
name: "Animation"
}
]
let services = [{
"name": "Logo",
"description": "Capture the essence of your brand with an unforgettable logo design.",
"icon": "logo.svg",
"category": "logo"
}]
function generateServices(amount) {
var content = "";
for (let q = 0; q < categories.length; q++) {
content += '<div class="col-12 main_titleCol"><div class="main_title"><h2 class="servicestitle">' + categories[q].name + '</h2></div></div>';
}
$('.services').html(content);
let servicesheading = $('.servicestitle');
// add the new items
for (let k = 0; k < amount; k++) {
console.log(servicesheading.html);
if (servicesheading.innerText == services[k].description) {
content += '<div class="col-lg-4 col-md-4"><div class="feature_item"><img class="img-fluid services-icon" src="img/services/SVG/' + services[k].icon + '"><h4>' + services[k].name + '</h4><p>' + services[k].description + '</p></div></div>';
}
}
}
generateServices(10)
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
<div class="services"></div>
The final outcome should look like this if all were to work:
1. Let's group our initial array of services by category:
const services = [
{ name: '...', category: '...', 'description': '...', 'icon': '...' },
{ name: '...', category: '...', 'description': '...', 'icon': '...' },
{ name: '...', category: '...', 'description': '...', 'icon': '...' },
...
];
const servicesByCategory = services.reduce((acc,el) => {
if (acc[el.category]) acc[el.category].push(el)
else acc[el.category] = [el];
return acc;
}, {});
servicesByCategory is an object where keys are service categories and values are arrays of services assigned to category:
{
service1: [ { name: '...', ... }, ... ],
service2: [ { name: '...', ... }, ... ],
service3: [ { name: '...', ... }, ... ],
...
}
2. Now you can process services one by one for each category:
let content = '';
for (let category in servicesByCategory) {
// Do what you want with category name
// Let's add category header as an example
content += '<div class="col-12 main_titleCol"><div class="main_title"><h2 class="servicestitle">' + category + '</h2></div></div>';
for (let service of servicesByCategory[category]) {
// Proccess services one-by-one as you did before
content += '<div class="col-lg-4 col-md-4"><div class="feature_item"><img class="img-fluid services-icon" src="img/services/SVG/' + service.icon + '"><h4>' + service.name + '</h4><p>' + service.description +'</p></div></div>';
}
}
Related
how do I replace the for loop with .filter function in JavaScript.The matched name appears in the list.
let originalMoviesList = [ //Contains moviesname and url
{
name: "War Horse",
url: "War_Horse.jpg",
tag: "lepsum lepsum lepsum lepsum"
},{
name: "War Horse",
url: "War_Horse.jpg",
tag: "lepsum lepsum lepsum lepsum"
}
]
**let** matchedTerms = [];//`array for storing the matched terms`
searchTerm = searchTerm.toLowerCase();
for (let i = 0; i < originalMoviesList.length; i++) {
if ((originalMoviesList[i].name).toLowerCase().indexOf(searchTerm) !== -1) {
matchedTerms.push({//pushing into the array
name: originalMoviesList[i].name,//pushing name to the array of objects
url: originalMoviesList[i].url//pushing url to the array of objects
});
}
}
You are almost there. You just needed to put the condition inside the filter function
let originalMoviesList = [ //Contains moviesname and url
{
name: "War Horse",
url: "War_Horse.jpg",
tag: "lepsum lepsum lepsum lepsum"
}, {
name: "Star Horse",
url: "War_Horse.jpg",
tag: "lepsum lepsum lepsum lepsum"
}, {
name: "War Horse",
url: "War_Horse.jpg",
tag: "lepsum lepsum lepsum lepsum"
}
]
searchTerm = "star"; //searchTerm.toLowerCase();
let matchedTerms = originalMoviesList.filter(function(i) {
return i.name.toLowerCase().indexOf(searchTerm) > -1;
});
That filter can also be written with a fat arrow in EcmaScript 6 compatible code.
let originalMoviesList = [
{
name: "War Horse",
url: "War_Horse.jpg",
tag: "horse war"
},
{
name: "War Dolphin",
url: "War_Dolphin.jpg",
tag: "dolphin war"
}
];
let searchTerm = 'Horse';
let matchedTerms = originalMoviesList.filter( (movie) => movie.name
.toLowerCase()
.includes(searchTerm.toLowerCase()));
console.log(matchedTerms);
I'm trying to iterate over some JSON that I have included in my file and everything seems to be working fine up until I want to add my icons into each stakebox icon div. Any idea what might be going wrong? I want to add one icon if the value of my JSON object === true and one if the value === false.
$.each(stakeBox, function (i, stakeBoxData) {
var jsonDate = stakeBoxData.data_change_date;
var winLoss = stakeBoxData.win;
var points = stakeBoxData.amount_stakebox;
var winLoss = stakeBoxData.win;
var id = stakeBoxData.id;
if (stakeBoxDay < jsonDate) {
var self = $(this);
console.log(this.win);
$('.stakebox-container').append('\
<div id="' + id + '" class="stakebox-message-container">\
<div id="stakebox-icon"></div>\
<div><h5 id="stakebox-game"></h5></div>\
<div><h5 id="stakebox-points">' + points + '</h5></div>\
</div>\
');
if (this.win === true) {
$('#stakebox-icon').append('<i class="far fa-smile face"></i>');
} else {
$('.stakebox-message-container').css('background', '#a20000');
$('#stakebox-icon').append('<i class="far fa-frown face"></i>');
};
// console.log(i);
} else {
// console.log('nope');
}
});
Here is some of the JSON for reference:
var stakeBox = [{
id: "1",
amount: "40.00",
user_id: "1",
amount_stakebox: "33",
win: true,
data_change_date: "20180229",
username: "bkessler",
game_id: "1380",
team_id: "791",
status: "1"
}, {
id: "2",
amount: "1.00",
user_id: "1",
amount_stakebox: "4124124",
win: false,
data_change_date: "20180429",
username: "bkessler",
game_id: "1380",
team_id: "791",
status: "1"
}];
I want to search by header and content. for now can only be based on content. any suggestions or can add from this source code. Thank you
Here is my HTML
<div id="list">
<input type="text" v-model="search">
<ol>
<li v-for="(items, key) in groupedItems">
<h3>{{ key }}</h3>
<p v-for="todo in items">{{ todo.name }}</p>
</li>
</ol>
</div>
here is preview code in js fiddle: https://jsfiddle.net/60jtkp30/9/
It may not be the cleanest solution, but based on your implementation in the jdfiddle, just changing the filter function would be enough (I think).
var list = new Vue({
el: '#list',
data: {
search: '',
items: [
{ name: 'mike', type: 'student' },
{ name: 'beckham john', type: 'footballer' },
{ name: 'walcott', type: 'footballer' },
{ name: 'cech', type: 'footballer' },
{ name: 'jordan', type: 'actor' },
{ name: 'tom', type: 'actor' },
{ name: 'john', type: 'actor' }
]
},
computed: {
groupedItems() {
const arr = {}
//fungsi search
var searchResult = this.items.filter( todo => {
return todo.name.toLowerCase().indexOf(this.search.toLowerCase())>-1 || todo.type.toLowerCase().indexOf(this.search.toLowerCase())>-1;
} )
//grouping
for(var i = 0; i < searchResult.length; i++) {
const key = searchResult[i].type
if (arr[key]) {
arr[key].push(searchResult[i])
} else {
arr[key] = [searchResult[i]]
}
}
return arr
}
}
})
EDIT: I fixed the typo but nothing changes
I have the following array in a JS file:
var directory = [
{ type: "file", name: "file1.txt" },
{ type: "file", name: "file2.txt" },
{ type: "directory", name: "HTML Files", files: [
{ type: "file", name: "file1.html" },
{ type: "file", name: "file2.html" }
]},
{ type: "file", name: "file3.txt" },
{ type: "directory", name: "JavaScript Files", files: [
{ type: "file", name: "file1.js" },
{ type: "file", name: "file2.js" },
{ type: "file", name: "file3.js" }
]}
];
Also in JS file:
window.onload = function() {
var directoryContainer = document.querySelector("#outputList1");
var directoryList = "<ul>";
for (var i = 0; i < directory.length; i++)
{
if (directory[i].type == "file")
{
directoryList += "<li>" + directory[i].name + "</li>";
}
else if (directory[i].type == "directory")
{
directoryList += "<li>" + directory[i].name + "<ul>" + "<li>";
for (var j = 0; j < directory[i].length; j++)
{
directoryList += directory[j].files.name + "</li>";
}
directoryList += "</ul>";
directoryList += "</li>";
}
}
directoryList += "</ul>";
directoryContainer.innerHTML = directoryList;
};
In my HTML file:
<h3> Files </h3>
<head>
<script src = "js/list.js"></script>
</head>
<body>
<div id = "outputList1"></div>
</body>
It then prints on my website:
Files // title
-file1.txt
-file2.txt
-HTML Files
//Nothing here
-file3.txt
-JavaScript Files
//Nothing here
However in the areas where I commented nothing here, it's supposed to print the filenames when the type is a directory. The error is occurring somewhere in my for loop, but I'm not sure where. The final answer should look like this
Files // title
-file1.txt
-file2.txt
-HTML Files
- file1.html
- file2.html
-file3.txt
-JavaScript Files
-file1.js
-file2.js
-file3.js
You have two problems. The typo, as mentioned in the comments, and your inner for loop is iterating over directory[i], instead of directory[i].files. So change:
for (var j = 0; j < directory[i].length; j++) {...}
to
for (var j = 0; j < directory[i].files.length; j++) {...}
Also, might I suggest looking into recursion? It's a hard idea to comprehend at first, but you'll find uses for it over and over. Using it here would dramatically reduce your code, making it cleaner, more readable, much more robust (as you would then be able to nest files and folders endlessly, just like they are on a real system), and less error-prone. I don't think you would have had this problem if you'd done something like this:
function mapFiles(files) {
return '<ul><li>' + files.map(function(item) {
if (item.type === 'file') {
return item.name
}
return item.name + mapFiles(item.files)
}).join('</li><li>') + '</li></ul>'
}
var directoryList = mapFiles(directory)
Check it out on this JSFiddle
Some issues:
The HTML tags are in the wrong order: h3 should be within the body element.
You have a typo in direcrotyList
directory[j].files.name should be directory[i].files[j].name and directory[i].length should be directory[i].files.length
This solution will not work if you have sub-(sub-)directories. Recursion is a solution to that.
Here is how you could do it:
function getFilesHtml(directory) {
return '<ul>' + directory.map(function (entry) {
return '<li>' + entry.name +
(entry.type == 'file' ? '' : getFilesHtml(entry.files))
+ '</li>';
}).join('') + '</ul>';
}
window.onload = function() {
var directory = [
{type: "file", name: "file1.txt"},
{type: "file", name: "file2.txt"},
{type: "directory", name: "HTML Files", files: [
{type: "file", name: "file1.html"},
{type: "file", name: "file2.html"}
]},
{type: "file", name: "file3.txt"},
{type: "directory", name: "JavaScript Files", files: [
{type: "file", name: "file1.js"},
{type: "file", name: "file2.js"},
{type: "file", name: "file3.js"}
]}
];
document.querySelector("#outputList1").innerHTML = getFilesHtml(directory);
};
<h3> Files </h3>
<div id = "outputList1"></div>
I need to display related products in javascript on eBay listing.
I have that idea: I keep in array info about other listings like: url, image, price and tags attached to this product.
example:
some_product = [
tags: 'home, garden, kitchen',
url: http://listing.url,
price: 100
],
some_product_2 = [
tags: 'home, lifestyle, books',
url: http://listing2.url,
price: 120
]
and on listing I put code like:
<script type="text/javascript" src="http://domain.com/related_prod.js?keyword=home"></script>
And I expect that showed all the products with "home" in "tags". Can someone direct me to a solution?
First off, this is not a valid JavaScript or JSON:
some_product = [
tags: 'home, garden, kitchen',
url: http://listing.url,
price: 100
],
some_product_2 = [
tags: 'home, lifestyle, books',
url: http://listing2.url,
price: 120
]
The above should be replaced with the { } for objects.
{
some_product: {
tags: 'home, garden, kitchen',
url: http://listing.url,
price: 100
},
some_product_2: {
tags: 'home, lifestyle, books',
url: http://listing2.url,
price: 120
}
}
The above is a JavaScript object now. But this has been made better. Now, this being a pure JSON, it has to be added to a JavaScript variable. Consider this:
var products = {
some_product: {
tags: 'home, garden, kitchen',
url: http://listing.url,
price: 100
},
some_product_2: {
tags: 'home, lifestyle, books',
url: http://listing2.url,
price: 120
}
}
Now using the products, you can loop and put it as a list item.
var products = {
some_product: {
tags: 'home, garden, kitchen',
url: 'http://listing.url',
price: 100
},
some_product_2: {
tags: 'home, lifestyle, books',
url: 'http://listing2.url',
price: 120
}
}
var finalHtml = "";
for (var item in products) {
finalHtml += '<li><a href="' + products[item].url + '">' + item + '<\/a> <br \/>Tags: ' + products[item].tags + '<br \/>Price: ' + products[item].price + ' $</li>';
}
document.getElementById("products").innerHTML = finalHtml;
<ul id="products"></ul>
See the snippet above.
Considering that's not valid JavaScript, we can restructure your code to something more usable for your scenario... Like this:
var products = [
{
name: 'some_product',
tags: ['home', 'garden', 'kitchen'],
url: 'http://example.com/1',
price: 100,
},
{
name: 'some_product_2',
tags: ['home', 'lifestyle', 'books'],
url: 'http://example.com/2',
price: 120,
}
];
From here, we can use Array.prototype.filter to fetch the results based on tags:
function category(tag) {
return products.filter(function(product){
if (~product.tags.indexOf(tag)) return product;
});
}
category('home');
// ...
Example
both Praveen Kumar and Jamen proved to be helpful. I joined their answers to create one code.
var products = [
{
name: 'some_product',
tags: ['home', 'garden', 'kitchen'],
url: 'http://example.com/1',
price: 100,
},
{
name: 'some_product_2',
tags: ['home', 'lifestyle', 'books'],
url: 'http://example.com/2',
price: 120,
},
{
name: 'some_product_3',
tags: ['garden', 'lifestyle', 'books'],
url: 'http://example.com/2',
price: 120,
}
];
var finalHtml = "";
function category(tag) {
return products.filter(function(product){
if (~product.tags.indexOf(tag)) {
finalHtml += '<li><a href="' + product.url + '">' + product.name + '<\/a><br \/>Price: ' + product.price + ' $</li>';
document.getElementById("products").innerHTML = finalHtml;
console.log(product.name);
}
});
}
category('home');
//category('garden');
<ul id="products"></ul>
https://jsfiddle.net/p5x2v2cb/
Thank you for answers.