I have a Jquery/Ajax call which updates cart details. At the moment I can't get the existing HTML in the cart-body(tablebody) to clear. The actual ajax request works and all items are added to cart but the original HTML entries stay. The particular code is here:
if (data.products.length > 0 ) {
productRows.html("")
$(cartBody).empty()
Jquery Function
function refreshCart() {
console.log("in current cart")
var cartTable = $(".cart-table")
var cartBody = cartTable.find(".cart-body")
var productRows = cartBody.find(".cart-product")
var cartTotal = cartTable.find(".cart-total-sec")
var productQuantity = cartTable.find(".cart-item-quanity")
var currentUrl = window.location.href
var refreshCartUrl = '/api/cart/'
var refreshCartMethod = "GET";
var data = {};
$.ajax({
url: refreshCartUrl,
method: refreshCartMethod,
data: data,
success: function(data) {
console.log("success")
console.log(data)
if (data.products.length > 0 ) {
productRows.html("")
$(cartBody).empty()
$.each(data.products, function(index, value) {
console.log(value)
console.log(data.count)
cartBody.append("<tr><td>" + value.quantity + " x" + "</td><td>"+ value.name + "</td><td>" + "£" + value.price + "</td></tr>")
})
cartTotal.find(".cart-total").text(data.total)
console.log(data.total)
} else {
window.location.href = currentUrl
}
},
error: function(errorData) {
console.log("error")
console.log(errorData)
}
})
}
HTML Form:
<div>
<h4>This is your shopping cart</h4>
<table class="cart-table">
<tr>These are the items in your basket and their respective totals</tr><br>
<tbody class="cart-body">
{% for item in cart.items %}
<form method="POST" action='{% url "shopping-cart-remove" %}'>
{% csrf_token %}
<tr class="cart-product"><span class="cart-item-quanity">{{ item.quantity }}</span> x {{ item.product.name }} = {{ item.subtotal }}</tr>
<input type="hidden" name='id' value='{{ item.product.id }}'>
<span class='remove-span'><button>remove</button><br></span>
</form>
</tbody>
{% endfor %}
<tr class="cart-total-sec"><td class="cart-price">{{ cart.total }}</td></tr>
</div>
Any help is really appreciated.
First you are making mistake, as i can see there's form in table, on refreshing you will lose that form so i guess you should append items in form not in .cart-body.
And for emptying html use cartBody.html(""); and you don't have to use productRows.html("") at all.
The issue as pointed out by Ultrazz008, was that the HTML was incorrectly formatted. For reference:
<table class="cart-table">
<tbody class="cart-body">
<form method="POST" class='form-product-ajax' action='{% url "shopping-cart-remove" %}' data-endpoint='{% url "shopping-cart-remove" %}'>
{% csrf_token %} {% for item in cart.items %}
<tr class=cart-product>
<td>{{ item.quantity}} x {{ item.product.name }} {{ item.subtotal }}
<input type="hidden" name='id' value='{{ item.product.id }}'>
<button class='remove-btn'>remove</button>
</td>
{% endfor %}
</tr>
</form>
</tbody>
<tr class="cart-total-sec">
<td class="cart-price">{{ cart.total }}</td>
</tr>
</table>
Related
I want to count the number of correct answers and display it.i tried many ways but couldn't go through.will appreciate if anybody can help me .Thanks in advance.
{% extends 'base.html' %}
{% block title%}Quiz{% endblock title %}
{% block content %}
<div class=" text-danger mt-5 text-center">
<!-- <h2><b id="count">Timer</b></h2> -->
<h3>+++Quiz on Indian Politics+++</h3>
<hr>
</div>
<div class="pt-5">
{% for item in obj %}
<table>
<tr>
<h2>Q{{item.id}}. {{item.question}}</h2><br>
</tr>
<tr>
<input type="radio" class="rd" name="{{item.id}}" id="opt1" value="{{item.opt1}}"> {{item.opt1}}</input><br>
</tr>
<tr>
<input type="radio" class="rd" name="{{item.id}}" id="opt2" value="{{item.op2}}"> {{item.opt2}}</input><br>
</tr>
<tr>
<input type="radio" class="rd" name="{{item.id}}" id="opt3" value="{{item.opt3}}"> {{item.opt3}}</input><br>
</tr>
<tr>
<input type="radio" class="rd" name="{{item.id}}" id="opt4" value="{{item.opt4}}"> {{item.opt4}}</input><br>
</tr>
<tr>
<label id="lb" class="rd" name="{{item.id}}" value="{{item.cor_ans}}" style='display:none;color:green'><b>The correct answer is: {{item.cor_ans}}</b></label>
</tr>
<tr>
</tr>
</table>
<hr> {% endfor %}
<div class="pt-4">
<button type="submit" class="btn btn-success" id="btn">Submit</button>
</div>
<div class="pt-3">
<b id="counter"></b>
<b id="ans"></b>
</div>
</div>
{% endblock content %}
{% block scripts %}
<script>
const rad = document.getElementsByClassName('rd')
const input = document.getElementsByTagName('input')
const bt = document.getElementById('btn')
const label = document.getElementsByTagName('label')
const counter = document.getElementById('counter')
var score = 0;
bt.onclick = function() {}
// JQuery code
$(document).ready(function() {
$('#btn').click(function() {
$('.rd').show();
$('.rd').attr("disabled", true);
});
});
// # javascript code
bt.addEventListener('click', function() {
for (i = 0; i < input.length; i++) {
if (input[i].type === 'radio') {
if (input[i].checked) {
document.getElementById('ans').innerHTML += "Q" + input[i].name + " The Answer you selected is: " + input[i].value + "<br>";
}
}
}
})
// var interval = setInterval(function(){
// document.getElementById('count').innerHTML=count;
// count--;
// if (count === 0){
// clearInterval(interval);
// document.getElementById('count').innerHTML='Done';
// alert("You're out of time!");
// }
// }, 1000);
// document.getElementsByClassName('counter').innerHTML = cnt;
// console.log(label[j].innerHTML.replace("<b>The correct answer is: ","").replace("</b>",""))
//
// if(label[j].innerHTML.replace("<b>The correct answer is: ","").replace("</b>","") == input[i].value){
// console.log("Hello")
// }
</script>
{% endblock scripts %}
I am new to Django and working on a eCommerce website and trying to improve cart functions.
I follow the course to use JavaScript to update the items in the cart like below code.
If I clicked the "add" or "remove" button on other page(like product list), it works fine.
However, when I tried to lick "remove" button on the cart page (where I can see all the products in the cart), it worked fine as the very first time, the item removed from the cart.
Afterward, I clicked the button, the page just refreshed. Then I clicked another time, it worked again. So it's like after the first item removed, I have to click two times to remove the item I want.
Below are my JavaScript Code, views.py, and my cart_home.html. Hope anyone could help get through this, I've been stuck for a week....
JavaScript
<script type="text/javascript">
$(document).ready(function(){
var productForm = $(".form-product-ajax") // id:#form-product-ajax
productForm.submit(function(event){
event.preventDefault();
console.log("Form is not sending");
var thisForm =$(this);
var actionEndpoint = thisForm.attr('data-endpoint');
var httpMethod = thisForm.attr('method');
var formData = thisForm.serialize();
$.ajax({
url: actionEndpoint,
method: httpMethod,
data: formData,
success: function (data) {
console.log("success");
console.log(data);
console.log("Added:",data.productAdded);
console.log("Removed:",data.productRemoved);
var submitSpan = thisForm.find(".submit-span")
if (data.productAdded) {
submitSpan.html('<button class="btn btn-danger btn-sm " type="submit" name="remove">Remove</button>')
} else {
submitSpan.html('<button class="btn btn-success btn-sm" type="submit" name="Add">Add to Cart</button>')
}
var navbarCount = $(".navbar-cart-count")
navbarCount.text(data.cartItemCount)
var currentPath = window.location.href
if (currentPath.indexOf("cart") != -1) {
refreshCart()
}
},
error: function (errorData) {
console.log("error");
console.log(errorData);
}
})
})
function refreshCart() {
console.log("in current cart");
var cartTable = $(".cart-table")
var cartBody = cartTable.find(".cart-body")
var productRows = cartBody.find(".cart-products")
var currentUrl = window.location.href
var refreshCartUrl ='api/carts'
var refreshCartMethod="GET";
var data={};
$.ajax({
url: refreshCartUrl,
method: refreshCartMethod,
data:data,
success:function(data) {
var hiddenCartItemRemoveForm = $(".cart-item-remove-form")
if (data.products.length>0) {
productRows.html("")
i = data.products.length
$.each(data.products,function (index,value) {
console.log(value);
var newCartItemRemove = hiddenCartItemRemoveForm.clone()
newCartItemRemove.css("display","none")
newCartItemRemove.find(".cart-item-product-id").val(value.id)
cartBody.prepend("<tr><th scope=\"row\">" + i +"</th><td><a href='" +value.url + "'>" + value.name +"</a>" + newCartItemRemove.html() + "</td><td>" + value.price + "</td></tr>")
i --
})
cartBody.find(".cart-subtotal").text(data.subtotal);
cartBody.find(".cart-tax").text(data.tax);
cartBody.find(".cart-total").text(data.total);
}else {
window.location.href = currentUrl;
}
},
error:function(errorData) {
console.log("error");
console.log(errorData);
}
})
}
})
</script>
Cart_home.html
{% extends "base.html" %}
{% block content %}
<h1>Cart</h1>
{% if cart.products.exists %}
<table class="table cart-table">
<thead>
<tr>
<th scope="col">#</th>
<th scope="col">Prodcut Name</th>
<th scope="col">Product Price</th>
</tr>
</thead>
<tbody class="cart-body">
{% for product in cart.products.all %}
<tr class='cart-products'>
<th scope="row">{{forloop.counter}}
<td>{{product.name}}
{% include "carts/snippets/remove-product.html" with product_id=product.id%} </th>
</td>
<td>${{product.price}}</td>
</tr>
{% endfor %}
<tr>
<th colspan='2'></th>
<td> <b>Subtotal : $</b><span class="cart-subtotal">{{cart.subtotal}}</span> </td>
</tr>
<tr>
<th colspan='2'></th>
<td> Tax : $<span class="cart-tax" >{{cart.tax}} </span></td>
</tr>
<tr>
<th colspan='2'></th>
<td> <b>Total : $</b><span class="cart-total">{{cart.total}} </span> </td>
</tr>
<tr>
<th colspan='2'></th>
<td> <a class="btn btn-success" href="{% url 'carts:checkout' %}">Checkout</a> </td>
</tr>
</tbody>
</table>
<div class="cart-item-remove-form" style='display:none'>
{% include "carts/snippets/remove-product.html" with product_id=product.id%}
</div>
{% else %}
<p class="lead">There is no porduct in your cart now! </p>
<p> <a class="btn btn-secondary" href="{% url 'products:list' %}">Go to check!</a> </p>
{% endif %}
{% endblock content %}
views.py
def cart_detail_api_view(request):
cart_obj, new_obj = Cart.objects.new_or_get(request)
products = [{
"ud":x.id,
"url":x.get_absolute_url(),
"name":x.name,
"price":x.price,
}
for x in cart_obj.products.all()]
cart_data ={"products":products,"subtotal":cart_obj.subtotal,"total":cart_obj.total,"tax":cart_obj.tax()}
return JsonResponse(cart_data)
def cart_update(request):
product_id = request.POST.get('product_id')
if product_id:
try:
product_obj = Product.objects.get(id=product_id)
except Product.DoesNotExist:
print("Show message to user, product does not exist")
raise("Producr does not exist")
return redirect("carts:home")
else:
cart_obj, new_obj = Cart.objects.new_or_get(request)
if product_obj in cart_obj.products.all():
cart_obj.products.remove(product_obj)
product_added = False
else:
cart_obj.products.add(product_obj) # cart_obj.products.add(1)
product_added = True
request.session['cart_items'] = cart_obj.products.count()
if request.is_ajax(): #Asynchronous JavaScript Anx XML / JSON(JaveScrtip Object Notation)
print("Ajax request")
json_data = {
"productAdded":product_added,
"productRemoved":not product_added,
"cartItemCount":cart_obj.products.count()
}
return JsonResponse(json_data)
return redirect("carts:home")
I have a grid with some items and I´d like to sum val_itemservico column from selected rows. My template sums all rows.
I´d like to sum val_itemservico column only for selected rows when I click on "Calcular" button. In this case, I need to know if ind_selecionado column is checked.
So, how can I do that?
HTML:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>ORÇAMENTO</title>
</head>
<h2>ORÇAMENTO</h2>
<form class=" bd-form-20 " action="#" name="form-name" method="GET">
{% csrf_token %}
<label>Serviço: </label>{{filter.form.servico}}
<button type = "submit" >OK</button>
<br><br>
</form>
<tbody>
<div class=" bd-customhtml-29 bd-tagstyles bd-custom-table">
<div class="bd-container-inner bd-content-element">
<table id="table" border="1" rules="all" cellspacing="0" cellpadding="10"> <!--width="100%" border="0" cellspacing="0" cellpadding="2">-->
<tr>
<th>Selecionar</th>
<th>ID Item Serviço</th>
<th>Item Serviço</th>
<th>Valor Serviço</th>
<th>Serviço</th>
</tr>
{% for item in response.object_list %}
<tr>
<td> <input type="checkbox" id="item.ind_selecionado"></td>
<td>{{ item.id }}</td>
<td>{{ item.desc_itemservico }}</td>
<td>{{ item.val_itemservico }}</td>
<td>{{ item.servico_id}}</td>
</tr>
{% endfor %}
{% if response.object_list %}
Total: {{ response.object_list|length }}
{% endif %}
<br><br>
</table>
<br><br>
Valores:<br>
{% for item in response.object_list %}
{{item.val_itemservico}}<br>
{% endfor %}
<br><br>
<span id="sumV"></span>
<script>
var table = document.getElementById("table");
getSum();
function getSum()
{
var sumVal = 0;
for (var i = 1; i < table.rows.length; i++){
sumVal = sumVal + parseInt(table.rows[i].cells[3].innerHTML);
}
console.log("Sum: " + sumVal)
}
</script>
<br><br>
<button onclick="getSum();">Calcular</button>
</div>
</div>
</tbody>
</html>
You have to test for the value of the check input inside your loop that calculate the sum
for (var i = 1; i < table.rows.length; i++){
sumVal = sumVal + parseInt(table.rows[i].cells[3].innerHTML);
}
should be replaced by something like :
for (var i = 1; i < table.rows.length; i++){
if(table.rows[i].cells[1].childNodes[0].checked){
sumVal = sumVal + parseInt(table.rows[i].cells[3].innerHTML);
}
}
SO I have a div which displays information from arrays. With my ajax script I am increasing a value in an array and I want the whole div to change accordingly... I have already made these changes, but I dont know how to change the whole div? DO I use .attr or something else?
This is the twig:
{% for key, item in cart %}
{% if key == info.id %}
<div class="input-append">
<input class="span1" style="max-width:34px" placeholder="{{ key }}" value="{{ item }}" id="appendedInputButtons" size="16" type="text" data-id="{{ key }}"/>
<i class="icon-minus"></i>
<i class="icon-plus"></i>
<button class="btn btn-danger" type="button"><a href="{{ path('cart_remove', {'id': key}) }}"><i class="icon-remove icon-white"></i></button>
</div>
</td>
<td>{{ info.getQtyPrice(item)|number_format(2, '.', ',')}}</td>
<td>{{ info.getQtyDiscount(item)|number_format(2, '.', ',')}}</td>
<td>{{ info.getQtyTax(item)|number_format(2, '.', ',') }}</td>
<td>{{ info.getQtyFinal(item)|number_format(2, '.', ',') }}</td>
</tr>
{% endif %}
{% endfor %}
With Ajax I am increasing or decreasing the quantity(quantity is the variable item). When I increase or decrease the quantity I want the whole div to change accordingly. For example if the products quantity is 1 the price is 50, when I increase the quantity I want the price to change to 100. This is my script:
$(document).ready(function () {
$(document).on('click', '.add', function (e) {
$this = $(this);
$.ajax({
type: 'POST',
url: 'add/quantity',
dataType: 'JSON',
data: {product: $this.parent('.input-append').find('input').data('id'),quantity: $this.parent('.input-append').find('input').val()},
success: function (data) {
if(data.success == false){
alert('error')
}else{
$this.parent('.input-append').val(data.amount)
}
}
});
});
Right now the line: $this.parent('.input-append').val(data.amount) only changes the quantity in the input field.
How can I change the whole div with the prices?
Answer
Thank you for your help. this code did the trick: $('.table').load(" .table");
add a class to each td you want to update like this :
<td class="qtyprice">{{ info.getQtyPrice(item)|number_format(2, '.', ',')}}</td>
<td class="qtytax">{{ info.getQtyDiscount(item)|number_format(2, '.', ',')}}</td>
<td>{{ info.getQtyTax(item)|number_format(2, '.', ',') }}</td>
<td class="qtyfinal">{{ info.getQtyFinal(item)|number_format(2, '.', ',') }}</td>
and your Ajax you update those fields accordingly by selecting them by class :
success: function (data) {
if(data.success == false){
alert('error')
}else{
$this.closest('tr').find('.input-append').val(data.amount) ;
$this.closest('tr').find('.qtyprice').val(data.qtyprice) ;
$this.closest('tr').find('.qtytax').val(data.qtytax) ;
$this.closest('tr').find('.qtyfinal').val(data.qtyfinal) ;
}
}
your ajax response data needs to have all the prices on success.
I use Silex Frame Work and I am trying to delete files in backend that listed in a table using the following code but fire bug is given me an error message "invalid regular expression flag a" And when i click on the DELETE link it goes to a white page.The code is:
<script type="text/javascript">
$(document).ready(function(){
$(".delete-file").live('click', function() {
itemRow = $(this).parent().parent().parent();
fileId = $(this).attr('file_id');
deleteURL = $(this).attr('href');
var html = "<div> Are you sure, you want to DELETE this file? </div>";
var dialog = $(html).dialog({
buttons: {
"Ok": function() {
$.ajax({
url : deleteURL,
type : 'DELETE',
success : function(data) {
itemRow.remove();
dialog.dialog("close");
},
error : function() {
dialog.dialog("close");
}
});
},
"Cancel": function() {
$(this).dialog("close");
}
}
});
return false;
});
});
</script>
and i use:
{% for row in result %}
<tr class="content {{ cycle(['odd', 'even'], loop.index) }}">
<td> {{ row.name }} </td>
<td> {{ row.user.username }} </td>
<td class="url"> {{ row.path | truncate(30) }} </td>
<td> <img src="{{conf('base_url')}}/{{row.thumbnail}}"/> </td>
<td class="url"> {{ row.size | bytes_format}} </td>
<td> {{ row.description }} </td>
<td>
<span>DELETE</span>
</td>
</tr>
{% endfor %}
I found it. it's just because of giving wrong path to my .js files!!