Related
I have a problem. I have a timeline.
In this timeline I would like to indicate the whole events for each year. More precisely, I want to indicate all the months in the year that exist.
What is the best way to loop through all the months and years so that I don't have to repeat everything?
So I want to show all unique years on the one hand and then all unique months.
During the months I would then like to display the individual dates.
import React, { useState, useEffect } from "react";
import { useHistory } from "react-router-dom";
function Event() {
events = [
{
eventid: 6,
name: "Event 1",
description: "This is the first event.",
date: "10.10.2023",
status: "XO",
},
{
eventid: 8,
name: "Event 2",
description: "This is a another event",
date: "14.01.2023",
status: "XO",
},
{
eventid: 8,
name: "Event 3",
description: "This is the last event",
date: "14.03.2024",
status: "OS",
},
];
const result = {};
for (let e of res.data) {
const [_, m, y] = e.datum.split(".");
const yn = parseInt(y);
const mn = parseInt(m);
if (!result[yn]) result[yn] = [];
if (!result[yn].includes(mn)) result[yn].push(mn);
}
for (let y in result) {
result[y] = result[y]
.sort()
.map((m) =>
new Date(2020, m - 1, 1).toLocaleString("en-US", { month: "long" })
);
}
return (
<div>
<div className="timeline is-centered">
<header className="timeline-header">
<span className="tag is-medium is-primary">2023</span>
</header>
<div className="timeline-item is-primary">
<div className="is-primary"></div>
<div className="timeline-content"></div>
</div>
<header className="timeline-header ">
<span className="tag is-primary">January</span>
</header>
<div className="timeline-item is-primary">
<div className="timeline-marker is-primary is-danger is-icon">
<i className="fa fa-flag"></i>
</div>
<div className="timeline-content">
<p className="heading">14. January</p>
<p>Event 2</p>
<p>This is a another event.</p>
</div>
</div>
<header className="timeline-header ">
<span className="tag is-primary">October</span>
</header>
<div className="timeline-item is-primary">
<div className="timeline-marker is-primary is-danger is-icon">
<i className="fa fa-flag"></i>
</div>
<div className="timeline-content">
<p className="heading">10. Januar</p>
<p>Event 1</p>
<p>This is the first event.</p>
</div>
</div>
<header className="timeline-header">
<span className="tag is-medium is-primary">2024</span>
</header>
<div className="timeline-item is-primary">
<div className="is-primary"></div>
<div className="timeline-content"></div>
</div>
<header className="timeline-header ">
<span className="tag is-primary">March</span>
</header>
<div className="timeline-item is-primary">
<div className="timeline-marker is-primary is-danger is-icon">
<i className="fa fa-flag"></i>
</div>
<div className="timeline-content">
<p className="heading">14. Januar</p>
<p>Event 3</p>
<p>This is the last event</p>
</div>
</div>
<header className="timeline-header"></header>
</div>
</div>
);
}
export default Event;
What I want
const Sheet = [
{
"Code": "A-0-1",
"UPC": "Photos/4009803054728.jpg",
"Title": "U.S.S. Constitution",
"Price": "$34",
"InStock": "7"
},
{
"Code": "A-0-2",
"UPC": "Photos/4009803073996.jpg",
"Title": "Revell 07399 VW Samba Bus Model Kit",
"Price": "$38",
"InStock": "8"
},
]
const productsEl = document.querySelector(".Sheet");
function getProducts() {
Sheet.forEach((product) => {
productsEl.innerHTML += `<div class="productContainer">
<div class="img">
<img src=${product.UPC} alt="Image Unavailable" height="170px;" width="170px">
</div>
<div class="itemdesc">
<h2 class="itemName" id="itemName">${product.Title}</h2>
<h4 class="price"><span id="price">${product.Price}</span></h4>
<div class="desc">
<p id="desc">${product.Code}</p>
</div>
<div class="stock">
<p> ${product.InStock} Units</p>
</div>
<div class="addToCart" onclick="addToCart();">
<button id="addToCart" > Add to Cart</button>
</div>
</div>`;
})
}
getProducts();
function addToCart() {
console.log(document.getElementById("itemName").innerText)
}
<div class="Sheet">
</div>
All right, the add to cart button only logs the first data in my object. No matter which one I press it's always the first one. I tried .val and no luck. How can I log the item that was pressed instead?
You can pass the name of product as an argument to the addToCart() function
like below
const Sheet = [
{
"Code": "A-0-1",
"UPC": "Photos/4009803054728.jpg",
"Title": "U.S.S. Constitution",
"Price": "$34",
"InStock": "7"
},
{
"Code": "A-0-2",
"UPC": "Photos/4009803073996.jpg",
"Title": "Revell 07399 VW Samba Bus Model Kit",
"Price": "$38",
"InStock": "8"
},
]
const productsEl = document.querySelector(".Sheet");
function getProducts() {
Sheet.forEach((product) => {
productsEl.innerHTML += `<div class="productContainer">
<div class="img">
<img src=${product.UPC} alt="Image Unavailable" height="170px;" width="170px">
</div>
<div class="itemdesc">
<h2 class="itemName" id="itemName">${product.Title}</h2>
<h4 class="price"><span id="price">${product.Price}</span></h4>
<div class="desc">
<p id="desc">${product.Code}</p>
</div>
<div class="stock">
<p> ${product.InStock} Units</p>
</div>
<div class="addToCart" onclick="addToCart(product.Title);">
<button id="addToCart" > Add to Cart</button>
</div>
</div>`;
})
}
getProducts();
function addToCart(productTitle) {
console.log(productTitle)
}
You have to pass the product's index as a parameter to the AddToCart() function.
Advantages of this implementation
Allows you to access other properties of the product's object like Price, InStock, etc.
If you change the property name of "Title" to something else, you only need to update the AddToCart function code, not the getProducts()'s AddToCart call-to-action.
Advice: You should try to avoid fetching items via html id or innerText (this was a norm a decade or more ago, not anymore). Try using more of data attributes
const Sheet = [
{
"Code": "A-0-1",
"UPC": "Photos/4009803054728.jpg",
"Title": "U.S.S. Constitution",
"Price": "$34",
"InStock": "7"
},
{
"Code": "A-0-2",
"UPC": "Photos/4009803073996.jpg",
"Title": "Revell 07399 VW Samba Bus Model Kit",
"Price": "$38",
"InStock": "8"
},
]
const productsEl = document.querySelector(".Sheet");
function getProducts() {
Sheet.forEach((product, productIndex) => {
productsEl.innerHTML += `<div class="productContainer">
<div class="img">
<img src=${product.UPC} alt="Image Unavailable" height="170px;" width="170px">
</div>
<div class="itemdesc">
<h2 class="itemName" id="itemName">${product.Title}</h2>
<h4 class="price"><span id="price">${product.Price}</span></h4>
<div class="desc">
<p id="desc">${product.Code}</p>
</div>
<div class="stock">
<p> ${product.InStock} Units</p>
</div>
<div class="addToCart" onclick="addToCart(`+productIndex+`);">
<button id="addToCart" > Add to Cart</button>
</div>
</div>`;
})
}
getProducts();
function addToCart(productIndex) {
var product = Sheet[productIndex];
console.log(product.Title);
}
<div class="Sheet">
</div>
Explanation
The parameters of a forEach function allows for the index of the current iteration. read more here
Try like this
const Sheet = [
{
"Code": "A-0-1",
"UPC": "Photos/4009803054728.jpg",
"Title": "U.S.S. Constitution",
"Price": "$34",
"InStock": "7"
},
{
"Code": "A-0-2",
"UPC": "Photos/4009803073996.jpg",
"Title": "Revell 07399 VW Samba Bus Model Kit",
"Price": "$38",
"InStock": "8"
},
]
const productsEl = document.querySelector(".Sheet");
function getProducts() {
Sheet.forEach((product) => {
productsEl.innerHTML += `<div class="productContainer">
<div class="img">
<img src=${product.UPC} alt="Image Unavailable" height="170px;" width="170px">
</div>
<div class="itemdesc" >
<h2 class="itemName" id="itemName">${product.Title}</h2>
<h4 class="price"><span id="price">${product.Price}</span></h4>
<div class="desc">
<p id="desc">${product.Code}</p>
</div>
<div class="stock">
<p> ${product.InStock} Units</p>
</div>
<div class="addToCart" onclick="">
<button class="addToCartBtn" id="${product.Code}"> Add to Cart</button>
</div>
</div>`;
})
}
getProducts();
var elements = document.querySelectorAll(".addToCartBtn");
elements.forEach(element => {
element.addEventListener("click", function (e) {
console.log(e.target.id);
//other function
});
});
<div class="Sheet">
</div>
Use this instead...
const productsEl = document.querySelector(".Sheet");
const Sheet = [
{
"Code": "A-0-1",
"UPC": "Photos/4009803054728.jpg",
"Title": "U.S.S. Constitution",
"Price": "$34",
"InStock": "7"
},
{
"Code": "A-0-2",
"UPC": "Photos/4009803073996.jpg",
"Title": "Revell 07399 VW Samba Bus Model Kit",
"Price": "$38",
"InStock": "8"
},
];
(function getProducts() {
Sheet.forEach(product => {
productsEl.innerHTML += `<!-- ${product.Title} -->
<div class="productContainer">
<div class="img">
<img src="${product.UPC}" alt="${product.Title}" height="170px" width="170px">
</div>
<div class="itemDesc">
<h2 class="name">${product.Title}</h2>
<h4 class="price">${product.Price}</h4>
<div class="desc">
<p>${product.Code}</p>
</div>
<div class="stock">
<p> ${product.InStock} Units</p>
</div>
<div class="addToCart">
<!-- This will ensure you're only getting the current product (via the button) -->
<button onclick="addToCart(this)"> Add to Cart</button>
</div>
</div>`;
})
})();
function addToCart(button) {
const parent = button.closest('.productContainer');
// This will travel up the DOM chain from the button to the nearest element with `class="... productContainer ..."`
const element = parent.querySelector('.name');
// This will travel back down the DOMchain to the element with `class="... name ..."`
console.log(element.innerText);
}
<div class="Sheet"></div>
I have this array of object that contains info string number array
I'm trying to print all the info of touristActivities inside an html <section>
I want to print first the information of stepOne in a section tag then the information of stepTwo in another section tag
touristActivities array can contain more the these two steps
my code below i can only print the info without the section
How can i print the info of each steps inside a different section for each step
example:
<section class="stepOne">
all step One information
</section>
<section class="stepTwo">
all step Two information
</section>
const database = [{
sectorId: 1,
sectorName: "السياحة",
sectorIcon: "icon-1.png",
sectorN: "tourism",
licenseTitle: ["إصدار ترخيص مرافق الإيواء السياحي", "الأنشطة السياحية"],
licenseDesc: ["تقديم خدمات الترخيص لنشاط الفنادق والشقق المخدومة والمخيمات والنزل وفنادق الكبائن والشاليهات.", "تقديم خدمات الترخيص لوكالات السياحة والسفر وتنظيم الرحلات السياحية وحجز وحدات الإيواء السياحي وتسويقها."],
licenseNum: ["7960", "7961"],
touristActivities: [
stepOne = {
subTitle: "إصدار رخصة استثمار للمستثمر الأجنبي",
description: "إصدار رخصة استثمار لغير السعوديين لمزاولة الأنشطة التجارية بما يتوافق مع الاشتراطات والمتطلبات المحددة.",
},
stepTwo = {
subTitle: "إصدار سجل تجاري",
description: "وثيقة قانونية تحتوي على بيانات التاجر والنشاط التابع له تمكنه من مزاولة نشاطه بتصريح رسمي وفق الاشتراطات والمتطلبات المحددة.",
}
]
},
{
sectorId: 2,
},
];
let title = document.querySelector(".title");
let rightSection = document.querySelector('.right');
function getInfo(id) {
for (let i = 0; i < database.length; i++) {
if (database[i].sectorId === parseInt(id)) {
title.innerHTML += `<img src='img/${database[i].sectorIcon}' alt='image'>`;
title.innerHTML += `<h2>${name}</h2>`;
for (let j = 0; j < database[i].touristActivities.length; j++) {
subTitle(database[i].touristActivities[j].subTitle);
description(database[i].touristActivities[j].description);
}
}
}
}
getInfo(1);
function subTitle(st) {
let subTitle = `<div class='subTitle'>
<h3>${st}</h3>
</div>`;
rightSection.innerHTML += subTitle;
}
function description(desc) {
let description = `
<div class="discription">
<div class="description-inner parent">
<div class="descText">
<img src="img/description.png" alt="desc">
<h4>وصف الخطوة</h4>
</div>
<i class="fas fa-angle-down"></i>
</div>
<div class="descInfo toggle">
<p>${desc}</p>
</div>
</div>
`;
rightSection.innerHTML += description;
}
<div class="container">
<div class="title">
</div>
<div class="right">
<div class="subTitle">
</div>
</div>
<div class="left"></div>
</div>
The thing is your functions directly modify the HTML. It is tightly coupled. So you lose quite a bit of control over the output. With your code the sequence of these function calls is important because the output will depend on the calls. E.g. first description() must be followed by time(). Now you want to wrap all this, but you have already written it to the DOM.
The sections span the content you want to generate from each step. Therefore, they have to wrap everything inside the for-loop there.
Instead of directly modifying the DOM, write the output of your functions to an array buffer. After the loop you will attach the whole content that you have created to the section element.
So you return the HTML from your functions, store it into the array buffer and once you looped over the section, you can combine/add the content with buffer.join('') and close it.
This way, you split the generators from the assembly code.
Here is a working example:
const database = [{
sectorId: 1,
sectorName: "السياحة",
sectorIcon: "icon-1.png",
sectorN: "tourism",
licenseTitle: ["إصدار ترخيص مرافق الإيواء السياحي", "الأنشطة السياحية"],
licenseDesc: ["تقديم خدمات الترخيص لنشاط الفنادق والشقق المخدومة والمخيمات والنزل وفنادق الكبائن والشاليهات.", "تقديم خدمات الترخيص لوكالات السياحة والسفر وتنظيم الرحلات السياحية وحجز وحدات الإيواء السياحي وتسويقها."],
licenseNum: ["7960", "7961"],
touristActivities: [
stepOne = {
subTitle: "إصدار رخصة استثمار للمستثمر الأجنبي",
description: "إصدار رخصة استثمار لغير السعوديين لمزاولة الأنشطة التجارية بما يتوافق مع الاشتراطات والمتطلبات المحددة.",
duration: "يوم واحد",
money: "٢٠٠٠",
year: "سنة - ٥",
concernedParty: ["وزارة الاستثمار"],
concernedPartyLogo: ["thumbnail_2.png"],
address: "<iframe src='https://www.google.com/maps/embed?pb=!1m18!1m12!1m3!1d3622.702432314261!2d46.721452214877665!3d24.771389754922634!2m3!1f0!2f0!3f0!3m2!1i1024!2i768!4f13.1!3m3!1m2!1s0x3e2efd91f30ee055%3A0x13c696d4f4a80ec3!2sHRSD%20Ministry!5e0!3m2!1sen!2slb!4v1639075198016!5m2!1sen!2slb' width='100%' height='180' style='border:0;' allowfullscreen='' loading='lazy'></iframe>",
phone: "١٩٩١١",
website: "https://hrsd.gov.sa/ar",
mail: "info#hrsd.gov.sa",
requirements: ["ألا يكون النشاط الاستثماري ضمن قائمة الأنشطة المستثناة من الاستثمار الأجنبي.", "أن تكون مواصفات المنتج مطابقة للمواصفات السعودية أو الخليجية أو الدولية.", "ألا يكون طالب الترخيص قد صدرت ضده قرارات نهائية بسبب مخالفات لأحكام النظام داخل المملكة أو خارجه.", "أن يلتزم طالب الترخيص بالشروط والتعهدات الملحقة بنموذج طلب الترخيص الاستثماري.", "أن يحقق منح الترخيص أهداف الاستثمار وتطبيق هذه الشروط والضوابط على طلبات تجديد الترخيص."],
needs: [
"صورة السجل التجاري وعقد التأسيس للمنشاة في بلدها مصدقة من الجهات المختصة والسفارة السعودية.",
"صورة من حجز الاسم التجاري من وزارة التجارة.",
"مشروع عقد تأسيس شركة ذات مسؤولية محدودة صورة من.",
"مشروع عقد التأسيس والنظام الأساسي للشركة المساهمة صورة من.",
"إرفاق قرار الشركاء رغبتهم في الاستثمار في المملكة موضحاً به أسماء الشركاء ورأس المال ونسبة ملكية كل شريك والمركز الرئيس للمنشأة وطبيعة النشاط.",
"تعيين المدير العام وتحديد صلاحياته مصدقًا من الجهات المختصة والسفارة السعودية.",
"صورة من جواز السفر للمدير العام.",
"صورة من الهوية الوطنية وبطاقة العائلة إذا كان أحد الشركاء يتمتع بالجنسية السعودية.",
"صورة من السجل التجاري لإثبات المهنة أو مستخرج من الأحوال المدنية.",
"تقديم موافقة مبدئية من الوزارات أو الهيئات المعنية إن كان النشاط يتطلب موافقة.",
"تقديم خطة عمل تفصيلية.",
"تقديم ميزانية للمنشاة طالبة الترخيص من خارج المملكة لفترة لا تقل عن 3 سنوات توضح سلامة الوضع المالي معتمدة من مكتب محاسبي ومصدقة من الجهاز المعني ومن سفارة المملكة.",
"إثبات القدرة المالية على الاستثمار بما يتناسب مع رأس مال المشروع وحصة كل شريك وبما يتناسب مع خطة العمل المقدمة."
],
linkTitle: "اضغط لاصدار الرخصة عبر المركز السعودي للأعمال",
link: "https://www.ncc.gov.sa/ar/Pages/default.aspx",
},
stepTwo = {
subTitle: "إصدار سجل تجاري",
description: "وثيقة قانونية تحتوي على بيانات التاجر والنشاط التابع له تمكنه من مزاولة نشاطه بتصريح رسمي وفق الاشتراطات والمتطلبات المحددة.",
duration: "حسب التصنيف",
money: "حسب التصنيف",
year: "",
concernedParty: ["وزارة التجارة"],
concernedPartyLogo: ["thumbnail_1.png"],
address: "<iframe src='https://www.google.com/maps/embed?pb=!1m18!1m12!1m3!1d3622.702432314261!2d46.721452214877665!3d24.771389754922634!2m3!1f0!2f0!3f0!3m2!1i1024!2i768!4f13.1!3m3!1m2!1s0x3e2efd91f30ee055%3A0x13c696d4f4a80ec3!2sHRSD%20Ministry!5e0!3m2!1sen!2slb!4v1639075198016!5m2!1sen!2slb' width='100%' height='180' style='border:0;' allowfullscreen='' loading='lazy'></iframe>",
phone: "١٩٩١١",
website: "https://hrsd.gov.sa/ar",
mail: "info#hrsd.gov.sa",
requirements: ["ألا يقل العمر عن 18 سنة.", "ألا يكون موظف حكومي.", "ألا يقل رأس المال عن 5000 ر.س.", "لا يشترط إصدار سجل فرعي إذا كان بنفس النشاط وبنفس المنطقة الإدارية."],
needs: [
"تقديم طلب لتأسيس الشركة إلكترونيًا عبر بوابة أعمال الشركات. aamal.sa",
"خطاب موقع من المؤسسين بتأسيس الشركة.",
"صورة بطاقة الأحوال.",
"ألا يقل رأس المال عن 500,000 ريال.",
"صورة من مشروع نظام الشركة الأساسي وعقد تأسيس الشركة.",
"مشروع نظام الشركة الأساسي وعقد تأسيس الشركة.",
"خطاب من الشركة بإصدار فرع شركة يتضمن مدينة الفرع ومدير الفرع مصدق من الغرفة التجارية.",
"التأكيد على المستثمر بالإيداع بعد انتهاء السنة المالية للشركة."
],
linkTitle: "اضغط لاصدار الرخصة عبر المركز السعودي للأعمال",
link: "https://www.ncc.gov.sa/ar/Pages/default.aspx",
}
]
},
{
sectorId: 2,
sectorName: "التعليم",
sectorIcon: "icon-2.png",
sectorN: "education",
licenseTitle: ["إصدار ترخيص مدرسة أهلية بمنهج وطني أو عالمي", "إصدار ترخيص مركز الإشراف والتدريب التربوي الأهلي", "إصدار ترخيص معاهد اللغات", "إصدار ترخيص منشأة تدريبية"],
licenseDesc: [],
licenseNum: ["7950", "7951"]
},
];
let title = document.querySelector(".title");
let subTitle = document.querySelector(".subTitle");
let rightSection = document.querySelector('.right');
function getInfo(id) {
for (let i = 0; i < database.length; i++) {
if (database[i].sectorId === parseInt(id)) {
title.innerHTML += `<img src='img/${database[i].sectorIcon}' alt='image'>`;
title.innerHTML += `<h2>${name}</h2>`;
const activities = database[i].touristActivities;
const contentBuffer = [];
for (let activity of activities) {
subTitle.innerHTML += `<h3>${activity.subTitle}</h3>`;
contentBuffer.push('<section>');
contentBuffer.push(description(activity.description));
contentBuffer.push(time(activity.duration));
contentBuffer.push(money(activity.money, activity.year));
contentBuffer.push(concerned(activity.concernedParty, activity.concernedPartyLogo, activity.address, activity.phone, activity.website, activity.mail));
contentBuffer.push(requirements(activity.requirements));
contentBuffer.push(needs(activity.needs));
contentBuffer.push(link(activity.linkTitle, activity.link));
contentBuffer.push('</section>');
}
rightSection.innerHTML = contentBuffer.join('');
}
}
}
getInfo(1);
function description(desc) {
return `
<div class="discription">
<div class="description-inner parent">
<div class="descText">
<img src="img/description.png" alt="desc">
<h4>وصف الخطوة</h4>
</div>
<i class="fas fa-angle-down"></i>
</div>
<div class="descInfo toggle">
<p>${desc}</p>
</div>
</div>
`;
}
function time(timeinfo) {
return `
<div class="time">
<div class="time-inner">
<div class="timeText">
<img src="img/time.png" alt="time">
<h4>المدة الزمنية</h4>
</div>
<img src="img/arrow.png" alt="arrow">
<p class="text">${timeinfo}</p>
</div>
</div>
`;
}
function money(m, y) {
return `
<div class="money">
<div class="money-inner">
<div class="moneyText">
<img src="img/money.png" alt="money">
<h4>المقابل المالي</h4>
</div>
<img src="img/arrow.png" alt="arrow">
<p class="text"><span>${m}</span> ر.س / <span>${y}</span> سنوات كحد أقصى</p>
</div>
</div>
`;
}
function concerned(a, b, m, p, w, e) {
return `
<div class="concerned">
<div class="concerned-inner parent">
<div class="concernedText">
<img src="img/jeha.png" alt="jeha">
<h4>الجهة المعنية</h4>
</div>
<i class="fas fa-angle-down"></i>
</div>
<div class="concernedInfo toggle">
<div class="concernedInfoContent">
<div class="box">
<img src="img/${b}" alt="logo" class="logo">
<h4 class="logoTitle">${a}</h4>
<p></p>
</div>
<div class="box">
<div class="locationTitle">
<img src="img/location.png" alt="location">
<h4>العنوان</h4>
</div>
<div class="map">${m}</div>
</div>
<div class="box">
<div class="phone">
<img src="img/phone.png" alt="phone">
<div class="phoneText">
<h4>الهاتف</h4>
مركز الاتصال الموحد s${p}
</div>
</div>
<div class="website">
<img src="img/almanasa-icon.png" alt="web">
<div class="websiteText">
<h4>المنصة الإلكترونية</h4>
${w}
</div>
</div>
<div class="mail">
<img src="img/bared.png" alt="mail">
<div class="webText">
<h4>البريد الإلكتروني</h4>
${e}
</div>
</div>
</div>
</div>
</div>
</div>
`;
}
function requirements(dt) {
return `
<div class="requirements">
<div class="requirements-inner parent">
<div class="requirementsText">
<img src="img/terms.png" alt="terms">
<h4>الاشتراطات</h4>
</div>
<i class="fas fa-angle-down"></i>
</div>
<div class="requirementsInfo toggle">
${dt.map(rq =>`<div class="inner-info">
<input type="checkbox" value="${rq}">
<p>${rq}</p></div>`).join("")}
</div>
</div>`;
}
function needs(dt) {
return `
<div class="needs">
<div class="needs-inner parent">
<div class="needsText">
<img src="img/needs.png" alt="needs">
<h4>المتطلبات</h4>
</div>
<i class="fas fa-angle-down"></i>
</div>
<div class="needsInfo toggle">
${dt.map(nd =>`<div class="inner-info">
<input type="checkbox" value="${nd}">
<p>${nd}</p></div>`).join("")}
</div>
</div>`;
}
function link(lt, li) {
return `
<div class="link">
<div class="link-inner parent">
<div class="linkText">
<img src="img/link.png" alt="link">
<h4>احصل على رخصتك عبر منصة الأعمال</h4>
</div>
<i class="fas fa-angle-down"></i>
</div>
<div class="linkInfo toggle">
${lt}
</div>
</div>`;
}
<div class="container">
<div class="title">
</div>
<div class="right">
<div class="subTitle">
</div>
</div>
<div class="left"></div>
</div>
Your code is not valid syntax.
Step one is inside an array and using '='
[step1 = {}, step2 = {}]
You will need to restructure it. Perhaps by adding a stepId field so you can mix it with other types.
[{stepId:'step1'},{stepId:'step2'},{not:'astep'}]
database.forEach(sector => {
const steps = sector.touristActivities.filter(activity=>activity.stepId !== undefined)
// Now use your `steps` to generate your sections.
steps.forEach(step=>{
const ele = document.createElement('section')
ele.className = step.stepId
ele.innerText = step.subTitle
// and so on
})
})
You can use Array.reduce() method to group activities by index:
let data = getDatabase();
// collect activities
let activities = [];
for (let sect of data) {
activities.push(sect.touristActivities);
}
// group by index
let groupedActivities = activities.reduce((groups, activities, index) => {
activities.forEach((step, i) => {
groups[i] = groups[i] || [];
groups[i].push(step);
});
return groups;
}, []);
// display in html <section>
groupedActivities.forEach((group, index) => {
let sec = document.createElement('section');
sec.innerHTML += `<hr><strong>Section step ${index + 1}</strong><br>`;
for (let act of group)
sec.innerHTML += `${act.subTitle}<br>`;
document.body.appendChild(sec);
});
function getDatabase() {
return [{
sectorId: 1,
sectorName: "sector Name",
licenseNum: ["7960", "7961"],
touristActivities: [
stepOne = {
subTitle: "sector1 stepOne",
description: "1 dsescription ",
},
]
},
{
sectorId: 2,
sectorName: "sector Name",
licenseNum: ["7960", "7961"],
touristActivities: [
stepOne = {
subTitle: "sector2 stepOne",
description: "sector2 dsescription",
},
stepTwo = {
subTitle: "sector2 stepTwo",
description: "sector2 dsescription",
},
]
},
{
sectorId: 3,
sectorName: "sector Name",
licenseNum: ["7960", "7961"],
touristActivities: [
stepOne = {
subTitle: "sector3 stepOne",
description: "sector3 dsescription",
},
stepTwo = {
subTitle: "sector3 stepTwo",
description: "sector3 dsescription",
},
stepThree = {
subTitle: "sector3 stepThree",
description: "sector3 dsescription",
}
]
},
];
}
If you are doing a lot of complex queries on object structure then you can use jsonpath library.
<script src="https://cdn.jsdelivr.net/npm/jsonpath#1.1.1/jsonpath.min.js"></script>
<script>
let activities = jsonpath.query(database, '$..touristActivities');
</script>
I have a HTML list with rearrangable divs, they can be moved up and down, once rearranged I need to change the array with the same order of the HTML elements.
HTML:
<div id="List">
<div id="listUnit2" class="row">
<div class="text-center" style="width:50px;">
<p>Orange</p>
</div>
</div>
<div id="listUnit1" class="row">
<div class="text-center" style="width:50px;">
<p>Pear</p>
</div>
</div>
<div id="listUnit0" class="row">
<div class="text-center" style="width:50px;">
<p>Apple</p>
</div>
</div>
</div>
Array:
"listArray": [
{
"id": 0,
"name": "apple",
},
{
"id": 1,
"name": "pear",
},
{
"id": 2,
"name": "orange",
},
]
How can I get this result using the id value as a reference?
"listArray": [
{
"id": 2,
"name": "orange",
},
{
"id": 1,
"name": "pear",
},
{
"id": 0,
"name": "apple",
},
]
I tried:
var unitsRows = document.querySelectorAll("#list .row");
var newList = [];
for (var row of unitsRows) {
var rowId = row.id
rowId = rowId.replace('listUnit', "");
var newEl = listArray[rowId];
newList.push(newEl);
}
listArray = newList;
The order of the objects changes but it's not the same of the HTML after some rearrangmet.
You can do this every time it changes.
I had to fix your invalid markup
const listArray = [...document.querySelectorAll("#List .row")]
.map(row => ({ id: +row.id.match(/\d+/g), name: row.querySelector('div').textContent.trim() }))
console.log(listArray)
<div id="List">
<div id="listUnit2" class="row">
<div class="text-center" style="width:50px;">
<p>Orange</p>
</div>
</div>
<div id="listUnit1" class="row">
<div class="text-center" style="width:50px;">
<p>Pear</p>
</div>
</div>
<div id="listUnit0" class="row">
<div class="text-center" style="width:50px;">
<p>Apple</p>
</div>
</div>
</div>
You can get the list on UI, then you sort the listArray based on it.
listArray.sort(function (a, b) {
return names.indexOf(a.name) - names.indexOf(b.name);
});
I updated your code and print the result in the console. You can check it:
var listArray = new Array({
"id": 0,
"name": "apple",
}, {
"id": 1,
"name": "pear",
}, {
"id": 2,
"name": "orange",
});
var unitsRows = document.querySelectorAll(".row p");
var names = [];
[].forEach.call(unitsRows, function(item) {
names.push(item.innerHTML.toLowerCase());
});
listArray.sort(function (a, b) {
return names.indexOf(a.name) - names.indexOf(b.name);
});
console.log('Result', listArray);
<div id="List">
<div id="listUnit2" class="row">
<div class="text-center" style="width:50px;">
<p>Orange</p>
</div>
</div>
</div>
<div id="listUnit1" class="row">
<div class="text-center" style="width:50px;">
<p>Pear</p>
</div>
</div>
</div>
</div>
<div id="listUnit0" class="row">
<div class="text-center" style="width:50px;">
<p>Apple</p>
</div>
</div>
</div>
</div>
1- Your html code is wrong, modify the structure.
2- You have an element with id='List', not an element with class=list. And you need the children of that div, So modify your selector:
var unitsRows = document.querySelectorAll("#List .row");
3- Get text of p element with:
let text = document.querySelectorAll(`#${itm.id} p`)[0].textContent.trim();
var unitsRows = document.querySelectorAll("#List .row");
let newList = [];
unitsRows.forEach(itm => {
let text = document.querySelectorAll(`#${itm.id} p`)[0].textContent.trim();
newList.push({
id: itm.id.replace('listUnit', ""),
text
})
})
console.log(newList)
<div id="List">
<div id="listUnit2" class="row">
<div class="text-center" style="width:50px;">
<p>Orange</p>
</div>
</div>
<div id="listUnit1" class="row">
<div class="text-center" style="width:50px;">
<p>Pear</p>
</div>
</div>
<div id="listUnit0" class="row">
<div class="text-center" style="width:50px;">
<p>Apple</p>
</div>
</div>
</div>
I have a cart page with multiple products that have a new price. I now want to show the customer, using JS, how much he can save. For that I use my very basic knowledge of JS to write the old and new price into a variable, replace stuff I don't want in there like "€" and do my math. Then I create a new div with a certain text and how much the customer can save. What I want to achieve is that he writes that under every product.
As you can see from the snippet he only does that for the first product. I need some kind of loop or anything where he does that code for every product in the cart. So far I searched for 2 hours and couldn't find a hint. Maybe you guys and girls can help me.
var neuerpreis = document.querySelector(".price.price--reduced").childNodes[2].nodeValue.replace(/,/g, '.').replace(/ /g, '');
var alterpreis = document.querySelector(".price.price--reduced .price__old").childNodes[2].nodeValue.replace(/,/g, '.').replace(/ /g, '');
var difference = (alterpreis - neuerpreis).toFixed(2);
var newDiv = document.createElement("div");
var newContent = document.createTextNode(("You save ") + difference + (" €"));
newDiv.appendChild(newContent);
document.querySelector(".cart-item__price").appendChild(newDiv);
<div class="cart-item ">
<div class="cart-item__row">
<div class="cart-item__image">
<div class="cart-item__details">
<div class="cart-item__details-inner">
<div class="cart-item__price">
<div class="price price--reduced">
<span class="price__currency">€</span> 66,95<span class="price__old">
<span class="price__currency">€</span> 79,00</span>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="cart-item ">
<div class="cart-item__row">
<div class="cart-item__image">
<div class="cart-item__details">
<div class="cart-item__details-inner">
<div class="cart-item__price">
<div class="price price--reduced">
<span class="price__currency">€</span> 100,95<span class="price__old">
<span class="price__currency">€</span> 79,00</span>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
You can use querySelecetorAll and relative addressing
I select the .cart-item__price as the relevant container
Then I set some content as default
Note I do not convert to the string (toFixed) until I want to present it.
The INTL number formatter could also be used here
[...document.querySelectorAll(".cart-item__price")].forEach(div => {
const neuerpreis = div.querySelector(".price--reduced").childNodes[2].nodeValue.replace(/,/g, '.').replace(/ /g, '');
const alterpreis = div.querySelector(".price__old").childNodes[2].nodeValue.replace(/,/g, '.').replace(/ /g, '');
const difference = alterpreis - neuerpreis;
let newContent = document.createTextNode("No savings on this product")
const newDiv = document.createElement("div");
if (difference > 0) {
newContent = document.createTextNode(("You save ") + difference.toFixed(2) + (" €"));
}
newDiv.appendChild(newContent);
div.appendChild(newDiv);
})
<div class="cart-item ">
<div class="cart-item__row">
<div class="cart-item__image">
<div class="cart-item__details">
<div class="cart-item__details-inner">
<div class="cart-item__price">
<div class="price price--reduced">
<span class="price__currency">€</span> 66,95
<span class="price__old">
<span class="price__currency">€</span> 79,00
</span>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="cart-item ">
<div class="cart-item__row">
<div class="cart-item__image">
<div class="cart-item__details">
<div class="cart-item__details-inner">
<div class="cart-item__price">
<div class="price price--reduced">
<span class="price__currency">€</span> 100,95<span class="price__old">
<span class="price__currency">€</span> 79,00</span>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
var el = document.querySelectorAll(".test_class");
for (i = 0; i < el.length; i++) {
el[i].innerHTML = "test"+i
}
<div class="test_class">hey</div>
<div class="test_class">hey</div>
<div class="test_class">hey</div>
<div class="test_class">hey</div>
Here you go