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>
Related
I am trying to create Video gallery playlist using HTML CSS and JavaScript. I have created html and css and two js files
one to include all videos as shown here:
let allVideos = [
{
name: "Button Hover Effect",
src: "https://youtu.be/ykuD2QOZkhc",
id: "vid_1"
},
{
name: "Button Hover Effect",
src: "https://youtu.be/ykuD2QOZkhc",
id: "vid_2"
},
{
name: "Confirm Password using Html CSS & js",
src: "https://youtu.be/ykuD2QOZkhc",
id: "vid_3"
},
{
name: "Creative Card Hover Effect",
src: "https://youtu.be/ykuD2QOZkhc ",
id: "vid_4"
},
{
name: "Creative Digital Clock Ui Design",
src: "https://youtu.be/ykuD2QOZkhc",
id: "vid_5"
},
{
name: "Creative Our Team Section",
src: "https://youtu.be/ykuD2QOZkhc",
id: "vid_6"
},
{
name: "Filter Text Animation Using Html and CSS",
src: "https://youtu.be/ykuD2QOZkhc",
id: "vid_7"
},
{
name: "Glassmorphism Calculater New Design",
src: "https://youtu.be/ykuD2QOZkhc"
},
{
name: "How To Make Cheatsheet",
src: "https://youtu.be/ykuD2QOZkhc",
id: "vid_9"
},
{
name: "How to create Login Form",
src: "https://youtu.be/ykuD2QOZkhc",
id: "vid_10"
},
{
name: "How To Make Animated Menu Icon",
src: "https://youtu.be/ykuD2QOZkhc",
id: "vid_11"
},
{
name: "How to make Read More Function",
src: "https://youtu.be/ykuD2QOZkhc",
id: "vid_12"
},
{
name: "Vertical Navigation Bar",
src: "https://youtu.be/ykuD2QOZkhc",
id: "vid_13"
}
]
and one for the playlist script here
const mainVideo = document.querySelector('#main-Video');
const musicList = document.querySelector('.music-list');
const playlist = document.getElementById('playlist');
const AllLessons = document.querySelector('.AllLessons');
const videoTitle = document.querySelector('.title');
const ulTag = document.querySelector("ul");
AllLessons.innerHTML = `${allVideos.length} Lessons`
let musicIndex = 1;
window.addEventListener('load',()=>{
loadMusic(musicIndex);
playingNow();
})
function playMusic(){
mainVideo.play();
playlist.classList.add('active')
}
function loadMusic(indexNumb){
mainVideo.src = `${allVideos[indexNumb - 1].src}.mp4`;
videoTitle.innerHTML = `${indexNumb}. ${allVideos[indexNumb - 1].name}`
}
for(let i = 0; i < allVideos.length; i++){
let liTag = `<li li-index="${i + 1}">
<div class="row">
<span>${i + 1}. ${allVideos[i].name}</span>
</div>
<video class="${allVideos[i].id}" src="${allVideos[i].src}.mp4" style="display: none;" title="${allVideos[i].name}"></video>
<span id="${allVideos[i].id}" class="duration"></span>
</li>`;
playlist.insertAdjacentHTML('beforeend',liTag);
let liVideoDuration = ulTag.querySelector(`#${allVideos[i].id}`)
let liVideoTag = ulTag.querySelector(`.${allVideos[i].id}`);
liVideoTag.addEventListener("loadeddata", ()=>{
let videoDuration = liVideoTag.duration;
let totalMin = Math.floor(videoDuration / 60);
let totalSec = Math.floor(videoDuration % 60);
totalSec < 10 ? totalSec = "0"+ totalSec : totalSec
liVideoDuration.innerText = `${totalMin}:${totalSec}`;
liVideoDuration.setAttribute("t-duration", `${totalMin}:${totalSec}`);
})
}
const allLiTags = playlist.querySelectorAll('li');
function playingNow(){
for(let j = 0; j<allVideos.length; j++){
if(allLiTags[j].classList.contains('playing')){
allLiTags[j].classList.remove("playing")
}
if(allLiTags[j].getAttribute('li-index')==musicIndex){
allLiTags[j].classList.add('playing')
}
allLiTags[j].setAttribute("onclick", "clicked(this)")
}
}
function clicked(element){
let getIndex = element.getAttribute("li-index");
musicIndex = getIndex;
loadMusic(musicIndex);
playMusic();
playingNow();
}
everything working fine except the scr video in js "all Videos" file. it is not working.
can you please help to fix it?
Probably because of this line:
mainVideo.src = `${allVideos[indexNumb - 1].src}.mp4`;
The src property of the "video" object in allVideos returns a string, and you're concatenating that with '.mp4', not getting the source of the video.
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>';
}
}
For some reason, I cannot get my global variable counter to increase, even when it increases within the function I have the count++ occurring in. My outputted results are different between the text outputted within the function and the text outside of it. Any idea what I am doing wrong here? Shouldn't the count increase on each iteration of the survey.oncomplete function results?
Survey
.StylesManager
.applyTheme("modern");
var kn2 = "LwrHXqFRN_pszCopTKHF_Q"
var kn3 = "exroCUoYl4wVzs7pKU_49w"
var count = 0
var keyname = ("kn" + count)
var mapilink = "https://images.mapillary.com/" + (keyname) + "/thumb-1024.jpg";
var json = {
pages: [
{
name: "page1",
elements: [
{
type: "image",
name: "image",
imageLink: (mapilink),
imageHeight: 580,
imageWidth: 640
},
{
type: "html",
name: (keyname),
visible: false,
html: (keyname)
},
{
type: "rating",
name: "Walkability",
title: "How walkable does this look to you"
},
{
type: "rating",
name: "Saftey",
title: "How safe does this look to you"
},
{
type: "rating",
name: "Comfortability",
title: "How comfortable does this look to you"
}
]
}
]
}
window.survey = new Survey.Model(json);
var username = document.getElementById("user").value;
survey
.onComplete
.add(function (result) {
count ++;
var PID = document.getElementById("user").value;
var results = PID + "_" + (keyname) + ":\n" + JSON.stringify(result.data, null, 3) + (count) ;
document
.querySelector('#surveyResult')
.textContent = results;
survey.clear();
survey.render();
});
$("#surveyElement").Survey({model: survey});
Got an answer from a seperate stackexchange post - basically, I needed to wrap everything in more functions.
function outputting function text rather than expected output
I want to loop through an array of objects named tier1.
what I get is this:
TypeError: Cannot read property 'length' of undefined
My code looks something like this:
module.exports.getTier1= function(curUser, callback){
for (var i = 0; i < curUser.tier1.length; i++) {
var val = curUser.tier1[i];
console.log("index: " + i + " val: " + val);
}
};
var UserSchema = mongoose.Schema({
username: {
type: String,
index:true
},
password: {
type: String
},
email: {
type: String
},
name: {
type: String
},
tier1: [Tier1]
});
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.