Javascript search bar displaying holes in place of not displayed cards - javascript

so I'm building this online learning website, and I have a catalog of all courses where you can search for courses which titles or description contain the input in the search bar. I used bootstrap cards to make the catalog. It's working well, but on desktop I get empty spaces in place of the cards which are hidden, and the results show with big empty spaces between them is there were courses in between etc. No issue on mobile, all results show up vertically one after another. Is there a way to go around that? thanks!
Picture to see the "empty spaces"
JS code:
$('#live_search').on('keyup', function() {
let input = $(this).val();
$('.card').hide();
$('.card').filter(function() {
return new RegExp(input, 'i').test($(this).text())
}).show();
});
Cards:
<div class="search">
<form>
<label for="live_search">Rechercher une formation :</label>
<input type="text" id="live_search" size="30" class="form-control" placeholder="Rechercher une formation" />
</form>
</div>
<br>
<div class="container px-5 mb-3">
<div class="row">
{% for formation in formations %}
<div class="col-md-4">
<div class="card">
<img class="card-img-top" src="{{ vich_uploader_asset(formation, 'imageFile') }}" alt="{{ formation.imageName }}">
<div class="card-body">
<h5 class="card-title">{{ formation.title }}</h5>
<p class="card-text">{{ formation.description }}</p>
<a class="small btn btn-success custom-btn rounded-pill px-3" href="{{path('app_formations_see', {'id' : formation.id })}}" role="button">voir</a>
<span class="small">par {{ formation.user.firstname }} {{ formation.user.lastname }}</span>
</div>
</div>
</div>
{% endfor %}
</div>
</div>

You're hiding the card but keeping the col-md-4 div. You can merge the col-md-4 and card divs.

Just hide the col-md-4 div by introducing a "wrapper" class (or whatever you want to call it)
JS Code
$('#live_search').on('keyup', function() {
let input = $(this).val();
$('.wrapper').hide();
$('.wrapper').filter(function() {
return new RegExp(input, 'i').test($(this).text())
}).show();
});
Cards
<div class="search">
<form>
<label for="live_search">Rechercher une formation :</label>
<input type="text" id="live_search" size="30" class="form-control" placeholder="Rechercher une formation" />
</form>
</div>
<br>
<div class="container px-5 mb-3">
<div class="row">
{% for formation in formations %}
<div class="col-md-4 wrapper">
<div class="card">
<img class="card-img-top" src="{{ vich_uploader_asset(formation, 'imageFile') }}" alt="{{ formation.imageName }}">
<div class="card-body">
<h5 class="card-title">{{ formation.title }}</h5>
<p class="card-text">{{ formation.description }}</p>
<a class="small btn btn-success custom-btn rounded-pill px-3" href="{{path('app_formations_see', {'id' : formation.id })}}" role="button">voir</a>
<span class="small">par {{ formation.user.firstname }} {{ formation.user.lastname }}</span>
</div>
</div>
</div>
{% endfor %}
</div>
</div>

Related

Is there a way to change the style of a class under a #foreach tag using JavaScript?

I have been fiddling around with a project and can't seem to find a solution...it could be the lack of sleep, or I could just be missing something completely obvious.
The key here is I am currently changing the style of an ID...not a class. That ID is applied to the first link in the #foreach chain, but since it is an ID and not a Class, it is not applying the style to all items listed in #foreach (just the first).
Not sure if posting code here will be helpful since it is based on the tables I have in my DB, but maybe someone out there can lend a helping hand regardless.
The problem is in #foreach and the last two functions under the <script> tag.
#extends('layouts.app')
#section('content')
<style>
.link-window {
zoom:70%; }
.phone-width {
border-radius:10px; }
.form-control {
height:30px;
padding:0!important;
border:none!important;
border-radius:0!important;
display:inline-block; }
.form-group label {
float:center; }
#media (max-width:768px) {
.phone-width {
width:calc(100% - 24px);
margin-top:20px;
}
}
</style>
<div class="container">
<div class="row">
<div class="col-12 card p-3">
<h2 class="card-title">User Settings</h2>
<form action="/dashboard/settings" method="post">
<div class="row">
<div class="col-12 col-md-5">
<div class="form-group">
<label for="page_bg_color">Page Background Color</label>
<input type="color" id="page_bg_color" name="page_bg_color" class="form-control{{ $errors->first('page_bg_color') ? ' is-invalid' : '' }}" placeholder="#000000" value="{{ $user->page_bg_color }}">
#if($errors->first('page_bg_color'))
<div class="invalid-feedback">{{ $errors->first('page_bg_color') }}</div>
#endif
</div>
<div class="form-group">
<label for="page_text_color">Page Text Color</label>
<input type="color" id="page_text_color" name="page_text_color" class="form-control{{ $errors->first('page_text_color') ? ' is-invalid' : '' }}" placeholder="#000000" value="{{ $user->page_text_color }}">
#if($errors->first('page_text_color'))
<div class="invalid-feedback">{{ $errors->first('page_text_color') }}</div>
#endif
</div>
<div class="form-group">
<label for="link_bg_color">Link Background Color</label>
<input type="color" id="link_bg_color" name="link_bg_color" class="form-control{{ $errors->first('link_bg_color') ? ' is-invalid' : '' }}" placeholder="#000000" value="{{ $user->link_bg_color }}">
#if($errors->first('link_bg_color'))
<div class="invalid-feedback">{{ $errors->first('link_bg_color') }}</div>
#endif
</div>
<div class="form-group">
<label for="link_text_color">Link Text Color</label>
<input type="color" id="link_text_color" name="link_text_color" class="form-control{{ $errors->first('link_text_color') ? ' is-invalid' : '' }}" placeholder="#000000" value="{{ $user->link_text_color }}">
#if($errors->first('link_text_color'))
<div class="invalid-feedback">{{ $errors->first('link_text_color') }}</div>
#endif
</div>
<div class="col-12">
#csrf
<button type="submit" class="btn btn-primary mt-3{{ session('success') ? ' is-valid' : '' }}">Save Settings</button>
#if(session('success'))
<div class="valid-feedback">{{ session('success') }}</div>
#endif
</div>
</div>
<div id="page-bg-color" class="col-12 col-md-6 mx-auto phone-width" style="background-color:{{ $user["page_bg_color"] }};">
<div class="link-window py-5">
<div class="row">
<div class="main-content text-center py-3">
<h2 class="fw-bold">{{ $user["main_name"] }}</h2>
<p>Description Text</p>
</div>
</div>
<div class="row">
#foreach($user["links"] as $link)
<div class="link">
{{-- What I am styling --}}
<p
id="link-colors"
class="user-link d-block p-3 mb-3 mx-4 h5 text-center"
target="_blank"
rel="nofollow"
style="border-radius:10px;background-color:{{ $user["link_bg_color"] }};color:{{ $user["link_text_color"] }};"
>{{ $link["name"] }}</p>
</div>
#endforeach
</div>
</div>
</div>
</div>
</form>
</div>
</div>
</div>
<script>
document.getElementById("page_bg_color").addEventListener("input", function() {
document.getElementById("page-bg-color").style.backgroundColor = this.value;
});
document.getElementById("page_text_color").addEventListener("input", function() {
document.getElementById("page-text-color").style.color = this.value;
});
// Styling Controller (background-color)
document.getElementById("link_bg_color").addEventListener("input", function() {
document.getElementById("link-colors").style.setProperty("background-color", this.value, "important");
});
// Styling Controller (color)
document.getElementById("link_text_color").addEventListener("input", function() {
document.getElementById("link-colors").style.setProperty("color", this.value, "important");
});
</script>
#endsection
I've tried using .getElementByClassName and it didn't work.
Can you try using a for loop after document.getElementByClassName?
Like this:
<script>
const elements = document.getElementsByClassName('text');
for(const i in elements) {
elements[i].style.color='red';
}
</script>
In your foreach loop it looks like it is using the SAME id for every paragraph in that loop. You can't reuse IDs. in javascript, you can use querySelector and it will refer to the FIRST matching element.
In my answer, I added a new class called links to the parent of your foreach. Then user querySelector to refer to the FIRST link under links.
let firstLink = document.querySelector(".links .link p");
document.querySelector("#link_text_color").addEventListener("input", (e) => {
firstLink.style.setProperty("color", e.target.value, "important");
})
.link p {
padding: 10px;
}
<input id="link_text_color">
<div class="row links">
<div class="link">
<p class="user-link d-block p-3 mb-3 mx-4 h5 text-center" target="_blank" rel="nofollow" style="border-radius:10px;background-color:red;color:white">name</p>
</div>
<div class="link">
<p class="user-link d-block p-3 mb-3 mx-4 h5 text-center" target="_blank" rel="nofollow" style="border-radius:10px;background-color:gray;color:black">name 2</p>
</div>
</div>

Django project How to change an object from for loop (its a JSON response) to readable by Java-Script

I would like to make easy math in my currency Django project but I got response in google chrome inspect that one object (that which comes from API JSON response) is undefined but second is a String
When I change code a little bit to this below I got response in console inspect
And I can see clearly this object is there but I can't get it out of class .value
console.log(amount1, amount2);
<p id="crypto-price">3289.00221916 </p> <option id="user-wallet">15000 </option>
static/js/javascript.js
const amount1 = document.getElementById("crypto-price");
const amount2 = document.getElementById("user-wallet");
function calculate() {
console.log("YESS");
**console.log(parseInt(amount1.value) * parseInt(amount2.value));**
console.log(typeof amount1.value, typeof amount2.value);
}
calculate();
YESS
javascripts.js:13 NaN
javascripts.js:14 undefined string
Django templates where are both objects "crypto-price" "user-wallet" comes from the for loop
{% extends "web/layout.html" %}
{% block body %}
<div class="row">
{% for crypto_detail in crypto_detail_view %}
<div class="col-lg-12 col-md-6 mb-4">
<div class="card h-100">
<div class="card-body">
<img class="rounded mx-auto d-block" src="{{crypto_detail.logo_url}}" width="50" height="50">
<h4 class="card-title text-center" id="crypto-name">{{ crypto_detail.name }} </h4>
</div>
<div class="card-footer text-center">
<p id="crypto-price" >{{crypto_detail.price}} </p>
<p>{{fiat_currency}}</p>
</div>
<div class="card-footer text-center" >
<p href="">Price Date: {{ crypto_detail.price_date }}</p>
</div>
</div>
</div>
{% endfor %}
<div class="row g-3 align-items-center">
<p>Your Money:</p>
<select class="form-select" aria-label="Default select example">
<option selected>which currency do you want to buy Crypto for?</option>
{% for money_purchased in user_purchased_currencies %}
<p id="currency-name">{{money_purchased.currency}}</p>
<option id="user-wallet">{{money_purchased.currency_amount}} </option>
{% endfor %}
</select>
<form method="post" >
{% csrf_token %}
<div class="form-group">
<p>{{ form.wallet_amount }}</p>
<input type="text" value="{{crypto_name}}" />
</div>
<input class="btn btn-primary" type="submit" value="Buy">
</form>
</div>
</div>
{% block js_block %}
<script src="/static/js/javascripts.js" ></script>
{% endblock %}
{% endblock %}

how can i set the id of product to their own group?

Problem
The problem I'm facing is that i have a same products with different descriptions, so i had to group them in a dropdown respectively. Now when i change the value in the dropdown of the product, it changes the values in only the first product retrieved. The code and the screenshot of the issues are attached below.
Code
<script>
$(document).on("change", '.tranactionID', function (event) {
event.preventDefault();
$('#id_price').text($(this).children(":selected").attr("price"));
$('#id_sale_price').text($(this).children(":selected").attr("sale_price"));
let id = $('#ItemID').find(":selected").attr('transID');
console.log('Id : ',id)
let Url = `{% url 'cart:cart_add' 0 %}`.replace(0,id);
$('#transactionIDValue').attr('action', Url);
let formAction = $('#transactionIDValue').attr('action')
let formAction2 = $('#transactionIDValue').prop('action')
console.log('form action relative url : ',formAction)
console.log('form action full url : ',formAction2)
});
</script>
{% regroup transaction by productID as ProductList %}
{% for productID in ProductList %}
<div class="col-sm-3" id="productID" >
<div class="product">
<a href="{% url 'main:product-detail' productID.grouper.id %}" class="img-prod"><img class="img-fluid" src={{productID.grouper.product_image.url}} alt="" height="200px">
<span class="status" id="discount">%</span>
<div class="overlay"></div>
</a>
<div class="text py-3 pb-4 px-3 text-center">
<h3>{{productID.grouper}}</h3>
<div class="d-flex">
<div class="pricing">
<p class="price"><span class="mr-2 price-dc" id='id_price'>Rs. </span><span class="price-sale" id='id_sale_price'>Rs. </span></p>
</div>
</div>
<select class="tranactionID" id="ItemID" style="width: 250px;">
<option value="none" selected disabled hidden>
Select an Option
</option>
{% for val in productID.list %}
<option transID={{val.id}} price={{val.Price}} sale_price={{val.get_sale}} class="price_value" >{{val.AUID}} - {{val.Description}}</option>
{% endfor %}
</select>
<!-- <div class="bottom-area d-flex px-3">
<div class="m-auto d-flex"> -->
<form id='transactionIDValue' class="d-inline" method="post">
{{cart_product_form}}
{% csrf_token %}
<input type="submit" class="btn btn-primary shadow px-5 py-2" value="Add To Cart">
<!-- <button type="submit" class="btn btn-primary shadow px-5 py-2">Add to Cart</button> -->
</form>
<!-- </div> -->
<!-- </div> -->
</div>
</div>
</div>
{% endfor %}
Output
Now in the image attached above the issue is that i have change the value in the dropdown list of oranges but the price is updated at onions and even the id is passed to the add to cart button of onion. Can anyone help me with this issue.
You cannot use same ids for mutliple elements so change them to class selector . Then , inside your event handler use .closest() and .find() to change required elements values .
Demo Code :
$(document).on("change", '.tranactionID', function(event) {
//get closest outer div..
var selector = $(this).closest(".productID")
//find to get required elements..
selector.find('.id_price').text($(this).children(":selected").attr("price"));
selector.find('.price-sale').text($(this).children(":selected").attr("sale_price"));
let id = $(this).find("option:selected").attr('transID');
let Url = `{% url 'cart:cart_add' 0 %}`.replace(0, id);
selector.find("form").attr('action', Url);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.0/jquery.min.js"></script>
<!--added class-->
<div class="col-sm-3 productID">
<div class="product">
<a href="{% url 'main:product-detail' productID.grouper.id %}" class="img-prod"><img class="img-fluid" src={{productID.grouper.product_image.url}} alt="" height="200px">
<span class="status discount">%</span>
<div class="overlay"></div>
</a>
<div class="text py-3 pb-4 px-3 text-center">
<h3>Somethings,,</h3>
<div class="d-flex">
<div class="pricing">
<!--added class-->
<p class="price"><span class="mr-2 price-dc id_price">Rs. </span> <span class="price-sale">Rs. </span></p>
</div>
</div>
<select class="tranactionID" style="width: 250px;">
<option value="none" selected disabled hidden>
Select an Option
</option>
<option transID=1 price=234 sale_price=55 class="price_value">1 - abc</option>
<option transID=1 price=224 sale_price=55 class="price_value">2 - abc3</option>
</select>
<form id='transactionIDValue' class="d-inline" method="post">
<input type="submit" class="btn btn-primary shadow px-5 py-2" value="Add To Cart">
</form>
</div>
</div>
</div>
<div class="col-sm-3 productID">
<div class="product">
<a href="{% url 'main:product-detail' productID.grouper.id %}" class="img-prod"><img class="img-fluid" src={{productID.grouper.product_image.url}} alt="" height="200px">
<span class="status discount">%</span>
<div class="overlay"></div>
</a>
<div class="text py-3 pb-4 px-3 text-center">
<h3>Something</h3>
<div class="d-flex">
<div class="pricing">
<p class="price"><span class="mr-2 price-dc id_price">Rs. </span> <span class="price-sale">Rs. </span></p>
</div>
</div>
<select class="tranactionID" style="width: 250px;">
<option value="none" selected disabled hidden>
Select an Option
</option>
<option transID=2 price=234 sale_price=55 class="price_value">1 - abc</option>
<option transID=2 price=224 sale_price=55 class="price_value">2 - abc3</option>
</select>
<form class="d-inline" method="post">
<input type="submit" class="btn btn-primary shadow px-5 py-2" value="Add To Cart">
</form>
</div>
</div>
</div>

Javascript & Django: Event listener for form submit (Multiple forms using for loop) for AJAX

I tried posting before but I was not able to get a clear answer so I thought I would reframe it simply.
My template currently uses a for loop to print the posts of a "blog" and another for loop inside that to print comments belonging to the post.
Before I continue, just want to make it clear that my models and database is functioning. I even currently have a working comment section, it just keeps refreshing the page and so I would like to incorporate JS and AJAX instead.
Because I have multiple posts with their own comment sections, I tried creating individual id's for each form in the loop by saying . However, I am slightly confused as to how I am supposed to create an EventListener to make sure that no matter which of these forms are pressed, it takes the correct data and sends it to the backend.
Any help would be appreciated. Thank you! Code upon request is available. However, I would like to stress that it is unnecessary to ask for my model code as it works just fine.
{% for post in posts %}
<div class="mt-3 px-5 pt-4 pb-2 bg-white shadow-sm" style="border-top-left-radius: 0.5rem; border-top-right-radius: 0.5rem;">
<div class="row">
<div class="col-xs-1 pl-4">
<img class="rounded-circle post-image" src="{{ post.author.profile.image.url }}" />
</div>
<div class="col-xs-4 pt-1">
<a class="mr-2 post-author-name" href="#">{{ post.author.first_name }} {{ post.author.last_name }}</a>
<small class="text-muted post-time"><br>{{ post.date_posted|date:"F d, Y" }}</small>
</div>
<div class="col-xs-7 ml-3 pt-2">
Click for more options
</div>
</div>
<div class="row">
<div class="col-sm-12">
<p class="post-content">{{ post.content }}</p>
</div>
</div>
</div>
<div class="mb-3 pr-5 pt-4 pb-2 bg-light shadow-sm border-light" style="border-bottom-left-radius: 0.5rem; border-bottom-right-radius: 0.5rem;">
<div class="col-sm-12 pl-5 pb-5">
<form class="form-inline" method="POST" style="display:flex" id="{{forloop.counter}}"> {% csrf_token %}
<input type="search" name="comment" placeholder="New comment" class="form-control mr-sm-2 p-4" style="flex-grow:1;">
<button name="post_id" class="btn btn-info my-2 my-sm-0 " value="{{post.id}}" onclick='update_comments("{{forloop.counter}}")'> Post </button>
</form>
</div>
{% for comment in post.comments.all %}
<div class="row">
<div class="col-xs-1 offset-1 pl-4">
<img class="rounded-circle comment-image" src="{{ comment.author.profile.image.url }}" />
</div>
<div class="col-xs-4">
<a class="mr-2 comment-author-name" href="#">{{ comment.author.first_name }} {{ comment.author.last_name }}</a>
<small class="text-muted comment-time"><br>{{ comment.date_posted|date:"F d, Y" }}</small>
</div>
</div>
<div class="row">
<div class="col-sm-12 offset-1">
<p class="comment-content">{{ comment.content }}</p>
</div>
</div>
{% empty %}
<div class="px-5">
<p>No comments for this post.</p>
</div>
{% endfor %}
</div>
{% endfor %}

How to change timer for every single post in django

For every item in items I want to have a timer. I made a timer using javascript and I can show the timer for every single item. But when I want to show all the items in home page the timer is shown just for the last item. Is there any way to show the timer for all the items?
<div class="row m0 p0 justify-content-center">
{% for item in items %}
<div class="col-12 col-xs-6 col-md-4 card-item p0">
<div class="img-container">
<img class="rounded img-fluid img-thumbnail" src="{{MEDIA_URL}}{{ item.image }}" />
<div class="sold-img-item"></div>
{% if item.sold == 1 %}
<div class="sold">Sold
<div class="sold-price"><span>{{item.highest_bid_offer}} €</span></div>
</div>
{% endif%}
</div>
<h5 class="no-flow capital "><b>{{item.title}}</b></h5>
<div class="no-flow"><strong>Seller :</strong> {{item.seller}}</div>
<div class="no-flow">
<strong>Initial Price :</strong> <span>{{item.price}} €</span>
</div>
<input type="hidden" id="auction_status" name="auction_status" value="{{ item.auction_status }}"/>
<input type="hidden" id="end-time-fix" name="end-time-fix" value="{{item.auction_end_time}}"/>
<div class="timer-small" id="timer-small">
<div class="timer-small" id="days-small"></div>
<div class="timer-small" id="hours-small"></div>
<div class="timer-small" id="minutes-small"></div>
<div class="timer-small" id="seconds-small"></div>
</div>
<a class="divLinkkk" href="{% url 'item_detail' item.id %}"></a>
</div>
{% endfor %}
</div>
Elorbratiing what #Mithlesh has pointed out
You need to change your time code like this
<div class="timer-small">
<div class="timer-small days-small"></div>
<div class="timer-small hours-small"></div>
<div class="timer-small minutes-small"></div>
<div class="timer-small seconds-small"></div>
</div>
Then fix your javascript to work with class instead of id.

Categories

Resources