Can i querySelectorAll buttons that previously added with (element.innerHTML)? - javascript

I want to make array of all the buttons that inside the article tags.
When i select all buttons -i mentioned- that i added with (element.innerHTML) to use it in my JavaScript code,it doesn't work.
I tried to console.log the selected buttons but console gives me an empty array?
is there a wrong in my way of selection or there's another way to reuse that buttons in my JavaScript code?
const productsCenter = document.querySelector(".products-center");
class Displayproducts {
async getData() {
try {
let response = await fetch("products.json");
let data = await response.json();
let products = data.items;
let mapped = products.map((el) => {
const { title, price } = el.fields;
const image = el.fields.image.fields.file.url;
const id = el.sys.id;
return { title, price, image, id };
});
return mapped;
} catch (err) {
console.log(err);
}
}
}
class UI {
displayProducts(products) {
products.forEach((product) => {
let result = `<article class="product">
<div class="img-container">
<img
src="${product.image}"
alt="product"
class="product-img"
/>
<button class="bag-btn" data-id="${product.id}">
<i class="fas fa-shopping-cart"></i>
add to bag
</button>
</div>
<h3>${product.title}</h3>
<h4>${product.price}</h4>
</article>`;
productsCenter.innerHTML += result;
});
}
}
window.onload = () => {
const product = new Displayproducts();
const ui = new UI();
product.getData().then((products) => {
ui.displayProducts(products);
});
const bagBtns = [...document.querySelectorAll(".bag-btn")];
console.log(bagBtns);
};
<body>
<!-- start of nav bar -->
<nav class="navbar">
<div class="navbar-center">
<span class="nav-icon">
<i class="fas fa-bars"></i>
</span>
<img
src="C:\Users\iman\Desktop\comfy-house\images\logo.svg"
alt="logo"
/>
<div class="cart-btn"></div>
<span class="nav-icon">
<i class="fas fa-cart-plus"></i>
</span>
<div class="cart-items">0</div>
</div>
</nav>
<!-- end of nav bar -->
<!-- start of header -->
<header class="hero">
<div class="banner">
<h1 class="banner-title">furniture collection</h1>
<button class="banner-btn">shop now</button>
</div>
</header>
<!-- end of header -->
<!-- start of cart -->
<div class="cart-overlay">
<div class="cart">
<span class="close-cart">
<i class="fas fa-window-close"></i>
</span>
<h2>your cart</h2>
<div class="content"></div>
<!-- start of cart item -->
<!-- end of cart item -->
</div>
</div>
<!-- end of cart -->
<!-- start of products-->
<section class="products">
<div class="section-title">
<h2>our products</h2>
</div>
<div class="products-center">
</div>
</section>
<!-- end of products -->
<script src="app.js"></script>
</body>

In the window.onload function the const bagBtns = [...document.querySelectorAll(".bag-btn")]; line happened before the ui.displayProducts(products); line - you can see, add console.log('after') inside the callback function and see what happen.
This happen because - read this article
sulotions:
use async await
move the next lines:
const bagBtns = [...document.querySelectorAll(".bag-btn")];
console.log(bagBtns);
after:
ui.displayProducts(products);

Related

Why isn't forEach working after page refresh?

I want to add and remove 'selected-bullet' class but first time it is working and after refresh browser it is not working. why is not forEach working after page refresh?
const Resume = () => {
const bullets = document.querySelector('.bullets');
const bullet = document.querySelectorAll('.bullet');
[...bullet].forEach((el) => {
el.addEventListener('click', () => {
bullets
.querySelector('.selected-bullet')
.classList.remove('selected-bullet');
el.classList.add('selected-bullet');
});
});
return (
<div className='resume-bullets'>
<div className='bullet-container'>
<div className='bullet-icons'></div>
<div className='bullets'>
<div className='bullet selected-bullet'>
<i className='bi bi-mortarboard-fill bullet-logo'></i>
<span className='bullet-label'>Education</span>
</div>
<div className='bullet'>
<i className='bi bi-clock-history bullet-logo'></i>
<span className='bullet-label'>Work History</span>
</div>
<div className='bullet'>
<i className='bi bi-laptop bullet-logo'></i>
<span className='bullet-label'>Programming Skills</span>
</div>
<div className='bullet'>
<i className='bi bi-bar-chart-line bullet-logo'></i>
<span className='bullet-label'>Projects</span>
</div>
<div className='bullet'>
<i className='bi bi-palette bullet-logo'></i>
<span className='bullet-label'>Interests</span>
</div>
</div>
</div>
</div>
);
};

why the value of productsCenter variable is null?

i want to know wher the error came from, i'm trying to make an ecommerce project with vanilla javaScript, when i start display the products, json data is fetched correctly as a first step, but when i excecuted displayProducts() function it didn't work!
the error message i got:
Uncaught (in promise) TypeError: Cannot set property 'innerHTML' of null.
i tried console.log(document.querySelector("products-center")) but the result was null, i also made sure that the js script tag is after html tags.
const productsCenter = document.querySelector("products-center");
class Displayproducts {
async getData() {
try {
let response = await fetch("products.json");
let data = await response.json();
let products = data.items;
let mapped = products.map((el) => {
const { title, price } = el.fields;
const image = el.fields.image.fields.file.url;
const id = el.sys.id;
return { title, price, image, id };
});
return mapped;
} catch (err) {
console.log(err);
}
}
}
class UI {
displayProducts(products) {
products.forEach((product) => {
productsCenter.innerHTML = `<article class="product">
<div class="img-container">
<img
src="${product.image}"
alt="product"
class="product-img"
/>
<button class="bag-btn">
<i class="fas fa-shopping-cart"></i>
add to bag
</button>
</div>
<h3>${product.title}</h3>
<h4>${product.price}</h4>
</article>`;
});
}
}
window.onload = () => {
const product = new Displayproducts();
const ui = new UI();
product.getData().then((products) => {
ui.displayProducts(products);
});
};
<body>
<!-- start of nav bar -->
<nav class="navbar">
<div class="navbar-center">
<span class="nav-icon">
<i class="fas fa-bars"></i>
</span>
<!-- <img
src="https://i.pinimg.com/originals/dd/79/2d/dd792d5596291f410cb8e7ce10a7e91a.png"
alt="logo"
/> -->
<div class="cart-btn"></div>
<span class="nav-icon">
<i class="fas fa-cart-plus"></i>
</span>
<div class="cart-items">0</div>
</div>
</nav>
<!-- end of nav bar -->
<!-- start of header -->
<header class="hero">
<div class="banner">
<h1 class="banner-title">furniture collection</h1>
<button class="banner-btn">shop now</button>
</div>
</header>
<!-- end of header -->
<!-- start of cart -->
<div class="cart-overlay">
<div class="cart">
<span class="close-cart">
<i class="fas fa-window-close"></i>
</span>
<h2>your cart</h2>
<div class="content"></div>
<!-- start of cart item -->
<!-- end of cart item -->
</div>
</div>
<!-- end of cart -->
<!-- start of products-->
<section class="products">
<div class="section-title">
<h2>our products</h2>
</div>
<div class="products-center">
</div>
</section>
<!-- end of products -->
<script src="app.js"></script>
</body>
document.querySelector("products-center"); searches for a DOM element which tag is named "products-center" (something like: <products-center></products-center>). And since this doesn't exist, productsCenter doesn't contain any valid DOM, and so you cannot set its innerHTML.
I can see <div class="products-center"> in your HTML, so I guess you meant to use const productsCenter = document.querySelector(".products-center"); (note the .).

Using a function with parameters in a template literal

I am dynamically inserting html in to the DOM when a form is submitted. When this content is created, I would like to add a delete function when the corresponding button is created. The issue I am facing is that I am unsure how I can use a function in a template literal that has a parameter. My function keeps running when the page loads!
const deletePost = (id) => {
console.log("Delete Button Was clicked ");
}
function renderPost(title, date, body, author, id) {
// renderPost()
postHolder.innerHTML += `<div class="post">
<div class="deleteButton"><button onclick=${deletePost(id)}><i class="fas fa-trash"></i></button></div>
<div class="headerPosted">
<div class="titlePosted">
${title}
</div>
<div class="datePosted">
${date}
</div>
</div>
<div class="bodyPosted">
${body}
</div>
<div class="authorPosted">
-"${author}"
</div>
</div>`;
}
Here is a codepen to test: Codepen
Simply wrap the dynamic variable with ${...}
Try
<button onclick=deletePost(${id})>
Demo:
<script>
const deletePost = (id) => {
console.log("Delete Button Was clicked ");
}
document.addEventListener('DOMContentLoaded', (event) => {
function renderPost(title, date, body, author, id) {
// renderPost()
var postHolder = document.getElementById('postHolder');
postHolder.innerHTML += `<div class="post">
<div class="deleteButton"><button onclick=deletePost(${id})><i class="fas fa-trash"></i></button></div>
<div class="headerPosted">
<div class="titlePosted">
${title}
</div>
<div class="datePosted">
${date}
</div>
</div>
<div class="bodyPosted">
${body}
</div>
<div class="authorPosted">
-"${author}"
</div>
</div>`;
}
renderPost('test',new Date(),'some body','test author',123);
});
</script>
<link href="https://stackpath.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet" integrity="sha384-wvfXpqpZZVQGK6TAh5PVlGOfQNHSoD2xbE+QkPxCAFlNEevoEH3Sl0sibVcOQVnN" crossorigin="anonymous">
<div id="postHolder"></div>

call Load more function for active tab

I'm trying to develop a load more function for a specific tab pane, in this case, the active tab pane. I'm having issues with this jquery function because I'm calling the load more in the end of all tabs, and in my JS function I can't figure out how to load after the pane that is active, in which the button was clicked. This way I keep loading the questions in the last pane, but I couldnt print without var lastItem = $('div.question-col .question-summary:last');
$(document).ready(function () {
$(".load-more").on('click', function (e) {
var tab = $(this).data('tab');
var next_page = $(this).data('next-page');
console.log(next_page);
console.log(tab);
$.get($(this).data('url') + '?tab=' + tab + '&page=' + next_page, function (data) {
addNewQuestions($.parseJSON(data));
});
$(this).data('next-page', parseInt(next_page) + 1);
});
siteStats();
});
function addNewQuestions(objects) {
$.each(objects, function (i, object) {
console.log(object);
var lastItem = $('div.question-col .question-summary:last');
var newLine = lastItem.clone(true);
var newObject = newLine.find('.question-info');
updateTitleAndLink(newObject.find('.summary a'), object);
updateCreationDate(newObject.find('.question-updated-at'), object);
updateQuestionAnswers(newObject.find('.question-answers'), object);
updateAnswerCount(newObject.find('.answers-count'), object);
updateViewsCount(newObject.find('.views-count'), object);
updateVotesCount(newObject.find('.votes-count'), object);
updateSolvedStatus(newObject.find('.status'), object)
lastItem.after(newLine);
});
}
The update functions are not relevant to this case, I guess.
<div id="tabs" class="tab-content">
<ul>
<li>Recent Questions</li>
<li>Unanswered Questions</li>
<li>Top Scored Questions</li>
</ul>
{if empty($recent_questions)}
<div class = "col-sm-12" style = "text-align: center"><strong>No questions to load!</strong></div>
{/if}
{if !empty($recent_questions)}
<div id="recent_questions" class="question-col">
<!-- Questions come here -->
<div class = "load-more"
data-next-page = "1"
data-url = "{url('controller/api/questions/load_more_questions')}"
data-tab = "recent_questions">
<a id="loadMore">
Load More...
</a>
</div>
</div>
{/if}
<div id="unanswered_questions">
<!-- Questions come here -->
<div class = "load-more"
data-next-page = "1"
data-url = "{url('controller/api/questions/load_more_questions')}"
data-tab = "unanswered_questions">
<a id="loadMore">
Load More...
</a>
</div>
</div>
<div id="top">
<!-- Questions come here -->
<div class = "load-more"
data-next-page = "1"
data-url = "{url('controller/api/questions/load_more_questions')}"
data-tab = "top_scored_questions">
<a id="loadMore">
Load More...
</a>
</div>
</div>
//Questions come here - Question template
<div class="question-summary narrow">
<div class="question-info col-md-12">
<div class="votes">
<div class="votes-count">
<span title="{$question['votes_count']} votes">
{if $question['votes_count']}
{$question['votes_count']}
{else}
0
{/if}
</span>
</div>
<div>votes</div>
</div>
<div {if $question['solved_date']}
class="status answered-accepted"
{else}
class="status answer-selected"
{/if}
title="one of the answers was accepted as the correct answer">
<div class="answers-count">
<span title="{$question['answers_count']} answer">{$question['answers_count']}</span></div>
<div>answer</div>
</div>
<div class="views">
<div class="views-count">
<span title="{$question['views_counter']} views">{$question['views_counter']}</span></div>
<div>views</div>
</div>
<div class="summary question-title">
<h3>
<a href="{questionUrl($question['publicationid'])}"
data-base-question-url = "{questionUrl('')}"
style="font-size: 15px; line-height: 1.4; margin-bottom: .5em;">
{$question['title']}
</a>
</h3>
</div>
<div class = "statistics col-sm-12 text-right" style="padding-top: 8px">
<span>
<i class = "glyphicon glyphicon-time"></i>
<span class="question-updated-at">{$question['creation_date']}</span>
</span>
<span>
<i class = "glyphicon glyphicon-comment"></i>
<span class="question-answers">{$question['answers_count']}</span>
</span>
</div>
</div>
</div>
My question is: is there any way to put my loaded content after the last item of the active pane?
Kind regards

Sorting of divs in Jquery

My code have divs of movies which are used to display movie with poster, now i want jquery to sort divs for me on basis of title,
<!-- Movie -->
<div class="movie" title="Reservoir Dogs">
<div class="movie-image">
<span class="play"><span class="name">Reservoir Dogs |
Reservoir Dogs</span></span><img src="http://ia.media-imdb.com/images/M/MV5BMTQxMTAwMDQ3Nl5BMl5BanBnXkFtZTcwODMwNTgzMQ##._V1_SX300.jpg" alt="movie">
</div>
<div class="rating">
<p>RATING</p>
<div class="stars">
<div class="stars-in4">
</div>
</div>
<span class="comments"></span>
</div>
</div>
<!-- end Movie -->
<!-- Movie -->
<div class="movie" title="Saw">
<div class="movie-image">
<span class="play"><span class="name">Saw |
Saw</span></span><img src="http://ia.media-imdb.com/images/M/MV5BMjAyNTcxNzYwMV5BMl5BanBnXkFtZTgwMzQzNzM5MjE#._V1_SX300.jpg" alt="movie">
</div>
<div class="rating">
<p>RATING</p>
<div class="stars">
<div class="stars-in4">
</div>
</div>
<span class="comments"></span>
</div>
</div>
<!-- end Movie -->
<!-- Movie -->
<div class="movie" title="Scarface">
<div class="movie-image">
<span class="play"><span class="name">Scarface |
Scarface</span></span><img src="http://ia.media-imdb.com/images/M/MV5BMjAzOTM4MzEwNl5BMl5BanBnXkFtZTgwMzU1OTc1MDE#._V1_SX300.jpg" alt="movie">
</div>
<div class="rating">
<p>RATING</p>
<div class="stars">
<div class="stars-in4">
</div>
</div>
<span class="comments"></span>
</div>
</div>
<!-- end Movie -->
<!-- Movie -->
<div class="movie" title="Signs">
<div class="movie-image">
<span class="play"><span class="name">Signs |
Signs</span></span><img src="http://ia.media-imdb.com/images/M/MV5BNDUwMDUyMDAyNF5BMl5BanBnXkFtZTYwMDQ3NzM3._V1_SX300.jpg" alt="movie">
</div>
<div class="rating">
<p>RATING</p>
<div class="stars">
<div class="stars-in3">
</div>
</div>
<span class="comments"></span>
</div>
</div>
<!-- end Movie -->
<!-- Movie -->
<div class="movie" title="Stir of Echoes">
<div class="movie-image">
<span class="play"><span class="name">Stir of Echoes |
Stir of Echoes</span></span><img src="http://ia.media-imdb.com/images/M/MV5BMTU0OTAyMDQzNV5BMl5BanBnXkFtZTcwNTg1NjYyMQ##._V1_SX300.jpg" alt="movie">
</div>
<div class="rating">
<p>RATING</p>
<div class="stars">
<div class="stars-in4">
</div>
</div>
<span class="comments"></span>
</div>
</div>
<!-- end Movie -->
Now here is my current code
$(document).ready(function () {
var desc = false;
document.getElementById("sort").onclick = function () {
sortUnorderedList("movie", desc);
desc = !desc;
return false;
}
});
function sortUnorderedList(ul, sortDescending) {
if (typeof ul == "string")
var lis = document.getElementsByClassName("movie");
var vals = [];
for (var i = 0, l = lis.length; i < l; i++)
vals.push(lis[i]);
debugger;
vals.sort(function (a, b) { return a.title - b.title });
//vals[].title.sort();
if (sortDescending)
vals.reverse();
for (var i = 0, l = lis.length; i < l; i++)
lis[i].innerHTML = vals[i].innerHTML;
}
above code is not giving desired result
can u suggest better way to do it
You can significantly simplify your code if you use more jQuery, anyway you are using it. Entire code in this case will be:
$(document).ready(function () {
var desc = false;
$("#sort").click(function () {
sortUnorderedList("movie", desc);
desc = !desc;
});
});
function sortUnorderedList(ul, sortDescending) {
$('.' + ul).sort(function(a, b) {
return sortDescending ? a.title.localeCompare(b.title) : b.title.localeCompare(a.title);
}).appendTo('body');
}
Just note that instead of appendTo('body'), you should append to appropriate container that holds .movie elements. I'm appending to body because this is a container for movie divs in my demo.
Demo: http://jsfiddle.net/212oc0kw/

Categories

Resources