fix JavaScript #LoadMore button to load 5 items per page - Django
i want show 5 item per once then user click on LoadMore button then it will load more 5 items
how to do that with js ?
html code :
{% for mobile in mobileforhome %}
<div class="card-deck">
<div class="card mb-3" style="max-width: 800px;">
<div class="row no-gutters">
<div class="col-md-4">
<img style="height:100%;width:100%;border-radius:6.5px;" src="{{ mobile.get_image }}" class="rounded float-right" alt="...">
</div>
<div class="col-md-8">
<div class="card-body">
<h5 class="card-title" id="primary_site_pages_app_name_control"> <b>{{ mobile.name }}</b></h5>
<p class="card-text" id="font_control_for_all_pages">{{ mobile.app_contect|truncatechars_html:153|safe}}</p>
</div>
<div class="card-footer">
<small class="text-muted" id="date_post_control">{{ mobile.post_date}}</small>
<small class="firstsmall"><a class="bg-orange" href="{% url 'mobile' %}" id="tag_name_control">هواتف</a></small>
</div>
</div>
</div>
</div>
</div>
<hr>
{% endfor %}
<!-- show more button -->
<div class="text-center mt-4">
<a role="presentation" type="button" class="btn btn-secondary btn-lg loadMore" style="width:40%;color:white">Show More</a>
</div>
<!-- script controll the games ( show 6 game per page ) -->
<script src="https://code.jquery.com/jquery-3.1.0.js"></script>
<script>
const thumbnails = $(".card-deck .card mb-3");
let visibleThumbnails = 0;
function showThumbnailsUntil(index) {
for (var i = visibleThumbnails; i <= index; i++) {
if (i < thumbnails.length) {
$(thumbnails[i]).addClass('visible');
visibleThumbnails++;
} else {
break;
}
}
}
showThumbnailsUntil(2);
$(".loadMore").on("click",function(){
showThumbnailsUntil(visibleThumbnails + 2)
if(visibleThumbnails === thumbnails.length)
{
$(".loadMore").fadeOut(); //this will hide
//button when length is 0
}
})
</script>
<style>
.card-deck {
display: none;
}
.card-deck.visible {
display: block;
}
</style>
<!-- end script -->
this is my code but it don't work why ? (it's show button and you can press on it but it's do nothing ! it's show all items not 5 )
Related
Hi I created a web app with Django. In this app there are 6 cards with a button for increase and a button for decrease the quantity of food to buy. I have a problem: only the buttons in the first card work. Here's the HTML code
<div class="container">
<div class="row">
{% for roll in rolls %}
<div class="col-4">
<div class="card" style="width: 16rem;">
<img src="{{ roll.immagine.url }}" class="card-img-top" alt="...">
<div class="card-body">
<h5 class="card-title">{{ roll.nome }} Roll</h5>
<p class="card-text">€ {{ roll.prezzo }}</p>
<button id="incrementBtn" style="border-radius: 8px; background-color:orange;">+</button>
<span id="counter">0</span>
<button id="decrementBtn" style="border-radius: 8px; background-color: lightsalmon;">-</button>
Acquista
</div>
</div>
</div>
{% endfor %}
</div>
</div>
Here's the Javascript code:
document.addEventListener("DOMContentLoaded", function() {
let idCounter = "counter1, counter2, counter3, counter4, counter5, counter6";
let arrIdCounter = idCounter.split(", ");
console.log(arrIdCounter);
let valueCounter = document.getElementById('counter').innerHTML;
const incrementBtn = document.getElementById('incrementBtn');
const decrementBtn = document.getElementById('decrementBtn');
incrementBtn.addEventListener('click', () => {
console.log(valueCounter);
valueCounter++;
document.getElementById('counter').innerHTML = valueCounter;
console.log(valueCounter);
});
decrementBtn.addEventListener('click', () => {
if (valueCounter > 0)
{
valueCounter--;
}
document.getElementById('counter').innerHTML = valueCounter;
});
});
When you render your file you will have something like:
<div class="col-4">
<div class="card" style="width: 16rem;">
...
<button id="incrementBtn" ...>+</button>
...
<button id="decrementBtn" ...>-</button>
...
</div>
</div>
<div class="col-4">
<div class="card" style="width: 16rem;">
...
<button id="incrementBtn" ...>+</button>
...
<button id="decrementBtn" ...>-</button>
...
</div>
</div>
<div class="col-4">
<div class="card" style="width: 16rem;">
...
<button id="incrementBtn" ...>+</button>
...
<button id="decrementBtn" ...>-</button>
...
</div>
</div>
How your script may know which element take? You cannot have more than 1 html element with same id, they have to be unique. To do so, you may change you buttons' ids to:
<button id="incrementBtn_{{ poll.id }}" style="border-radius: 8px; background-color:orange;">+</button>
And your variable to array:
const incrementBtn = document.querySelectorAll('[id^="incrementBtn"]');
But then of course you have to use it in loop.
This is what my page looks like:
I have a sidebar which can change the contents of the page depending on the button clicked. When I click on About the page will look like this:
So I made this with Vanilla JS using inner.HTML.
PROBLEM: When I refresh the page, meaning the inner.HTML is not happening yet because I never clicked any buttons on the sidebar yet. My form submits properly and it does not redirect me to the API url used on the form. But, when I tried to click the About button and click Home button and try to submit the form again, it redirects me now to the API page used on the form. My guess is, there is something wrong with my vanillajs using inner.HTML.
CODE looks like this:
HTML:
{% extends 'base.html' %}
{% load crispy_forms_tags %}
{% load static %}
{% block script %}
<script type="text/javascript" src="{% static 'js/cms/cms.js' %}"></script>
{% endblock %}
{% block style %}
<link rel="stylesheet" type="text/css" href="{% static 'css/cms.css' %}">
{% endblock %}
{% block content %}
<div class="container">
<div class="sticky-sidebar-page">
<div class="sidebar">
<h3>Manage Site Contents</h3>
<div class="list-group">
<button class="list-group-item list-group-item-action active" aria-current="true" onClick="showHomeContent()" id="homeButton">Home</button>
<button class="list-group-item list-group-item-action" aria-current="true" onClick="showAboutContent()" id="aboutButton">About</button>
Contact Us
Sample Page
A disabled link item
</div>
</div>
<div class="sandbox">
<div class="page-content" id="page-content">
<!-- SCHOOL LOGO -->
<div class="card" id="school-logo">
<div class="card-body">
<h5>School Logo</h5>
<small>On display:</small> <br>
<img src="{{logo.image.url}}" id="img" class="card-img-top" alt="..." style="max-width: 10rem; max-height: 10rem;"> <br>
<small>Change:</small>
<form action="{% url 'changelogo' %}" method="POST" enctype="multipart/form-data" id="logo-form">
{% csrf_token %}
<div class="input-group mb-3">
<input type="file" name="image" class="form-control" required id="inputGroupFile02">
<button type="submit" class="input-group-text" for="inputGroupFile02">Upload
</button>
</div>
</form>
</div>
</div>
<!-- HOME CAROUSEL -->
<div class="card">
<div class="card-body">
<h5>Home Carousel</h5>
<small>On display:</small><br>
{% for pic in carouselpics %}
<img src="{{pic.image.url}}" class="card-img-top" alt="..." style="max-width: 15rem; max-height: 15rem;"> <br>
Label: {{pic.label}} <br>
Content: {{pic.content}}<br>
<span style="font-size: 20px;">
<span style="color: red;">
<i class="fas fa-trash-alt"></i>
</span>
<span style="color:brown">
<i class="far fa-edit"></i>
</span>
</span>
<br>
<hr>
{% endfor %}
</div>
</div>
</div>
</div>
</div>
</div>
<script type="text/javascript">
const csrftoken = "{{csrf_token}}"
//home contents
var changeLogoUrlView = "{% url 'changelogo' %}"
var schoolLogo = "{{logo.image.url|safe}}";
</script>
JS:
const pageContent = document.getElementById('page-content')
// Getting Home Page Contents
function getLogo(){
var url = "http://localhost:8000/web-content/api/changelogo/"
fetch(url)
.then((response) => response.json())
.then(function(data){
pageContent.innerHTML = `
<div class="card" id="school-logo">
<div class="card-body">
<h5>School Logo</h5>
<small>On display:</small> <br>
<img src="${data[0].image}" id="img" class="card-img-top" alt="..." style="max-width: 10rem; max-height: 10rem;"> <br>
<small>Change:</small>
<form action="http://localhost:8000/web-content/api/changelogo/" method="POST" enctype="multipart/form-data" id="logo-form">
<input type="hidden" name="csrfmiddlewaretoken" value="${csrftoken}" >
<div class="input-group mb-3">
<input type="file" name="image" class="form-control" required id="inputGroupFile02">
<button type="submit" class="input-group-text" for="inputGroupFile02">Upload
</button>
</div>
</form>
</div>
</div>
`
})
}
function showHomeContent(){
if ( document.getElementById("homeButton").className.match(/(?:^|\s)active(?!\S)/) ){
return;
}else{
document.getElementById('homeButton').classList.add('active')
}
if ( document.getElementById("aboutButton").className.match(/(?:^|\s)active(?!\S)/) ){
document.getElementById("aboutButton").classList.remove('active')
}
pageContent.innerHTML = ""
getLogo()
}
function showAboutContent(){
if ( document.getElementById("aboutButton").className.match(/(?:^|\s)active(?!\S)/) ){
return;
}else{
document.getElementById('aboutButton').classList.add('active')
}
if ( document.getElementById("homeButton").className.match(/(?:^|\s)active(?!\S)/) ){
document.getElementById("homeButton").classList.remove('active')
}
pageContent.innerHTML = `
this is about content
`
}
// formsssssss
// change logo
var logoform = document.getElementById('logo-form')
logoform.addEventListener('submit', function(e){
e.preventDefault()
let input = document.getElementById('inputGroupFile02');
let data = new FormData();
data.append('image',input.files[0]);
var url = "http://localhost:8000/web-content/api/changelogo/"
fetch(url,{
method: "POST",
headers: {
"X-CSRFToken": csrftoken,
},
body:data
})
.then((response) => response.json())
.then(function(data){
getLogo()
logo = document.getElementById('logo-div')
logo.innerHTML = ""
logo.innerHTML = `<img src="${data.image}" alt="no image provided" style="max-width: 7rem; max-height: 7rem;">`
})
})
views.py:
this is the view I am using to for the change logo form where the problem happens when submitting after the page is rendered with inner.HTML:
class ChangeLogo(generics.ListCreateAPIView):
authentication_classes = [SessionAuthentication, BasicAuthentication]
permission_classes = [IsAuthenticated, IsAdminUser]
serializer_class = SchoolLogoSerializer
queryset = SchoolLogo.objects.all()
I have a group of bootstrap cards. When i click a button in a card always retrieve information from thirst card. document.querySelectorAll('.fa-bookmark') works properly but document.querySelector(".card-title") inside click listener retrieve the first card information. I want information from which card i click.
document.addEventListener('DOMContentLoaded', () => {
document.querySelectorAll(".fa-bookmark").forEach(bookmark => {
bookmark.onclick = function(event) {
alert(document.querySelector(".card-title").innerHTML);
}
})
})
<div class="container">
<div class="row">
{% for article in news.articles %}
<div class="col-sm">
<div class="card" style="width: 18rem;">
<img class="card-img-top" src="{{article.urlToImage}}" alt="{{article.source.name}}">
<div class="card-body">
<i class="far fa-bookmark"></i>
<i class="fas fa-bookmark" id="dl_bookmark"></i>
<h5 class="card-title">{{article.title}}</h5>
<p class="card-text">{{article.description|truncatechars:100}}</p>
Read
</div>
</div>
</div>
{% endfor %}
</div>
</div>
I have a list of cards displayed via a for loop. On click I want to toggle some text.
It works fine for the top card, but when I click the card below, it toggles the first card.
This is the case even though i've given the cards different id's used in the javascript toggle function.
Any ideas about what i'm doing wrong?
<!-- HTML -->
{% for card in cards %}
<div class="card mb-3">
<div class="card-header">
<img class = "float:left mr-2 mt-1 small-profile-picture" src ="{{ card.creator.profile.image.url }}" >
<a class="mb-4 float-up" > {{ card.creator }}</a>
<small> <p class=mt-2> {{ card.date }} </p> </small>
</div> <!-- Card Header ender -->
<!-- Here we have the questions and answers -->
<div onclick="myFunction()" style="cursor: pointer;">
<div class="card-body mt-4">
<h5 class="card-title"> <a class="article-title">{{ card.question }}</a></h5>
<p id="myDIV{{card.card_id}}"> Click to see Answer </p>
<!-- <p class="card-text"> {{ card.answer}} </p> -->
</div> <!-- Card body ender -->
</div>
<!--Javascript -->
<script type="text/javascript">
function myFunction() {
var x = document.getElementById("myDIV{{card.card_id}}");
if (x.innerHTML === "Click to see Answer") {
x.innerHTML = "{{card.answer}}";
} else {
x.innerHTML = "Click to see Answer";
}
}
</script>
{% endfor %}
Thanks for reading
There's a lot of things I would do differently here if I'm honest, but to keep the solution as close to your code as possible, I'd suggest the following. Remove the <script> from within your loop - you're redefining the function every time it loops. This is unnecessary and will probably cause a bunch of undesired effects.
Separate the JavaScript and pass myFunction arguments, rather than hard-coding strings into the function.
This is untested, but should point you in the right direction.
<script type="text/javascript">
function myFunction(id, answer) {
// note the template literal syntax below,
// this is different to the handlebars provided by django.
let x = document.getElementById(`card-${id}`);
if (x.innerHTML === "Click to see Answer") {
x.innerHTML = answer;
} else {
x.innerHTML = "Click to see Answer";
}
}
</script>
{% for card in cards %}
<div class="card mb-3">
<div class="card-header">
<img class = "float:left mr-2 mt-1 small-profile-picture" src="{{ card.creator.profile.image.url }}" >
<a class="mb-4 float-up"> {{ card.creator }}</a>
<small> <p class=mt-2> {{ card.date }} </p> </small>
</div>
<div onclick="myFunction({{ card.card_id }}, {{ card.answer }})" style="cursor: pointer;">
<div class="card-body mt-4">
<h5 class="card-title"> <a class="article-title">{{ card.question }}</a></h5>
<p id="card-{{ card.card_id }}"> Click to see Answer </p>
</div>
</div>
</div>
{% endfor %}
I changed a bit the questions and answers block:
function myFunction(ele) {
ele.querySelector('.card-body.mt-4 .card-text').classList.toggle('d-none');
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/css/bootstrap.min.css">
<script src="https://cdn.jsdelivr.net/npm/popper.js#1.16.0/dist/umd/popper.min.js"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/js/bootstrap.min.js"></script>
<div onclick="myFunction(this)" style="cursor: pointer;">
<div class="card-body mt-4">
<h5 class="card-title"> <a class="article-title">{{ card.question }}</a></h5>
<p id="useless...."> Click to see Answer </p>
<!--- removed comment from the next line -->
<p class="card-text d-none"> This is the answer ....{{ card.answer}} </p>
</div> <!-- Card body ender -->
</div>
I am working with Django. Below is my JavaScript code, in this code, "hello world" is getting printed in console but when I am clicking add to cart, then "clicked" is not getting printed.
console.log("Hello world");
var updateBtns = document.getElementsByClassName('update-cart');
for (var i = 0; i < updateBtns.length; i++) {
updateBtns[i].addEventListener('click', function() {
var action = this.dataset.action;
console.log('clicked');
});
}
This is part of my HTML code containing the button:
<div class="container carousel-inner no-padding">
<div class="carousel-item active">
{% for i in product %}
<div class="col-xs-3 col-sm-3 col-md-3">
<div class="card" style="width: 18rem;">
<img src='/media/{{i.image}}' class="card-img-top" alt="...">
<div class="card-body">
<h5 class="card-title">{{i.product_name}}</h5>
<p class="card-text">{{i.desc}}</p>
<button data-product="pr{{i.id}}" data-actions="add"
class="btn btn-primary add-btn update-cart">
Add to Cart
</button>
</div>
</div>
</div>
{% if forloop.counter|divisibleby:4 and forloop.counter > 0 and not forloop.last %}
</div>
<div class="carousel-item">
{% endif %}
{% endfor %}
</div>
</div>
{% block js %}
<script type="text/javascript" src="{% static 'js/cart.js' %}"></script>
{% endblock %}
No errors are getting printed when running this. Please Help. Thanks in advance.
You likely want to do this
You missed an s on actions too
Delegate from the nearest static container, then you do not need to loop at all
window.addEventListener("load", function() { // on page load
document.querySelector(".container").addEventListener("click", function(e) {
const tgt = e.target;
if (e.target.classList.contains('update-cart')) {
const action = tgt.dataset.actions;
const product = tgt.dataset.product;
const title = tgt.closest(".card-body").querySelector(".card-title").innerText;
// or
const desc = tgt.previousElementSibling.innerText;
console.log(action, product, title, desc );
}
});
});
<div class="container carousel-inner no-padding">
<div class="carousel-item active">
<div class="col-xs-3 col-sm-3 col-md-3">
<div class="card" style="width: 18rem;">
<img src='/media/{{i.image}}' class="card-img-top" alt="...">
<div class="card-body">
<h5 class="card-title">Product 1</h5>
<p class="card-text">Description 1</p>
<button data-product="pr1" data-actions="add" class="btn btn-primary add-btn update-cart">Add to Cart</button>
</div>
</div>
</div>
<div class="col-xs-3 col-sm-3 col-md-3">
<div class="card" style="width: 18rem;">
<img src='/media/{{i.image}}' class="card-img-top" alt="...">
<div class="card-body">
<h5 class="card-title">Product 2</h5>
<p class="card-text">Description 2</p>
<button data-product="pr2" data-actions="add" class="btn btn-primary add-btn update-cart">Add to Cart</button>
</div>
</div>
</div>
<div class="carousel-item"></div>
</div>