I have a cart list of customer shopping
I save customer items with add to basket button to localStorage
I have 2 problems
First one my data of basket in page is old and need to updated without refresh page
Second in a quick show of my basket at the top repeat the old data with add to basket button every time
Its quick view of the basket
function quickCartShow() {
let basketNumber = document.getElementById("card-value-numbers");
let cartItemsList = $("#cart-item-list");
let quickCart;
let price = 0;
basketNumber.innerText = cartItems ? cartItems.length : 0 ;
cartItems && cartItems.map(item => {
quickCart =
`<div class="row m-0 border-bottom mb-1"><div class="col-4 p-0 pl-1 align-self-center"> <a class="w-100" href="#` +
item.product.url +
`"> <img draggable="false" class="w-100" src="#` +
item.product.mainpic +
`" alt="product img"></a></div><div class="col-8 p-0"><div><a class="w-100 text-muted cart-text" href="#` +
item.product.url +
`"><p>` +
item.product.title +
`</p></a></div> <div class="d-flex justify-content-between"><p class="text-muted"> ` +
item.quantity +
// TODO: Active delete part here
` عدد </p><a class="pl-3 text-muted del-btn" onclick="removeFromCartHandler(this)"><i class="fas fa-trash-alt"></i></a></div> </div></div>`;
let advancePrice;
if (item.length) {
advancePrice = item.quantity * item.length
item.product.advance_prices.map(adPrice =>{
advancePrice <= adPrice.max ? price += advancePrice * adPrice.vprice : price +=0
})
} else {
item.product.offtype == 0 ? price += (item.quantity * item.product.price) :
item.product.offtype == 1 ? price += (item.quantity * (((100-item.product.off)/100)*item.product.price)) :
item.product.offtype == 2 ? price += ((item.quantity * item.product.price) - item.product.off) : price+= 0;
}
$("#cart-value-price").text(numberWithCommas(price));
cartItemsList.append(quickCart);
});
}
and the basket part code is:
function cardItemsShow() {
let cartContainer = $('.cart-items-page');
let questPrice = $('#guest-prices');
let cartItemShow;
let price = 0;
let cartsItemParent = $('.cart-items-page');
cartsItemParent.find("tr").remove();
cartItems && cartItems.map((item,i) => {
var maxProduct = ((item.product.max && ( item.product.instock != 2 || (item.product.max < item.product.stock)))) ?
item.product.max : item.product.instock == 2 ? item.product.stock : null
console.log(item)
cartItemShow =
`<tr class="class='col-12 checkout-item">`+
`<td>`+
`<a href="#`
+ item.product.url +
`">` +
`<img draggable="false" src="#` +
item.product.mainpic +
`" alt"`
+ item.product.title +
`">` +
`</a>` +
`</td>` +
`<td class="text-right">`+
`<a class="text-muted" style="display: inline-block" href="#` + item.product.url +
`">` + item.product.title +
`</a></td>` +
`<td>
<span style="white-space: nowrap"> `
+
((item.length !== null) ? item.length + ' سانتی متر '
: '')
+
`</span>
</td>
<td>
<div>
<form class="`+item.id+ ` onsubmit="return false" >
<p class="mb-0">تعداد</p>
<div class="number-input">
<button
onclick="this.parentNode.querySelector('input[type=number]').stepDown(); $('#refresh-btn`+i+`').removeClass('d-none')" type="button"></button>
<input class="quantity number-picker" min="0" name="quantity" id="quantity" max="`+ maxProduct +`"
value="`+ item.quantity+`" type="number">
<button
onclick="this.parentNode.querySelector('input[type=number]').stepUp(); $('#refresh-btn`+i+`').removeClass('d-none')"
class="plus" type="button"></button>
</div>
<div class="pt-1">
<a class="btn btn-success refresh-btn d-none" id="refresh-btn`+i+`" href="#" onclick="updateCartShow()" >
<i class="fas fa-sync-alt"></i>
<span> بهروزرسانی</span>
<a/>
</form>
</div>
</div>
</td>
<td><spam>` +
numberWithCommas(item.product.price)
+
`
تومان
</spam>
</td>
<td>
<button onclick="removeFromCartHandler()" class="checkout-btn-remove remove-cart"> × </button>
</td>
</tr> `
cartContainer.append(cartItemShow)
let advancePrice;
if (item.length) {
advancePrice = item.quantity * item.length
item.product.advance_prices.map(adPrice =>{
advancePrice <= adPrice.max ? price += advancePrice * adPrice.vprice : price +=0
})
} else {
item.product.offtype == 0 ? price += (item.quantity * item.product.price) :
item.product.offtype == 1 ? price += (item.quantity * (((100 - item.product.off)/100)*item.product.price)) :
item.product.offtype == 2 ? price += ((item.quantity * item.product.price) - item.product.off) : price+= 0;
}
questPrice.text(numberWithCommas(price))
})
}
function updateCartShow() {
cardItemsShow();
quickCartShow();
}
updateCartShow()
document.addEventListener("visibilitychange", event => {
if (document.visibilityState === "visible") {
updateCartShow();
}
});
$(document).on("click", ".add-to-basket", function() {
console.log("aaaa");
updateCartShow();
});
});
Thanks for your help
Related
I have specific problem. When I press button "Dodaj produkt", the values of inputs that have been inserted, are cleared. For example, fields: name, count, price_netto, vat_rate, price_brutto, summary_entity. Even if they're filled, after I press the button the values are default. I don't know why does this happens but I hope that someone will explain it to me.
var id_count = 1;
var price_summary = 0;
function delete_product(id) {
document.getElementById(id).remove();
}
function change_brutto(id) {
var netto = replace_dots(document.getElementById("price_netto" + id));
var vat = replace_dots(document.getElementById("vat_rate" + id));
var count = replace_dots(document.getElementById("count" + id));
if (vat > 0) {
vat = vat / 100;
vat += 1;
var calc = netto * vat;
document.getElementById("price_brutto" + id).value = Math.round((calc + Number.EPSILON) * 100) / 100;
calc = calc * count;
document.getElementById("summary" + id).value = Math.round((calc + Number.EPSILON) * 100) / 100;
} else if (vat == "" || vat == 0) {
document.getElementById("vat_rate" + id).value = "0";
document.getElementById("price_brutto" + id).value = netto;
document.getElementById("summary" + id).value = netto * count;
} else {
alert("Wpisz poprawną stawkę VAT");
}
}
function change_netto(id) {
var brutto = replace_dots(document.getElementById("price_brutto" + id));
var vat = replace_dots(document.getElementById("vat_rate" + id));
if (vat > 0) {
vat = vat / 100;
vat += 1;
var calc = brutto / vat;
document.getElementById("price_netto" + id).value = Math.round((calc + Number.EPSILON) * 100) / 100;
} else if (vat == "" || vat == 0) {
document.getElementById("vat_rate" + id).value = "0";
document.getElementById("price_netto" + id).value = brutto;
} else {
alert("Wpisz poprawną stawkę VAT");
}
}
function replace_dots(string) {
newString = string.value.replace(",", ".");
return newString;
}
function vat_changed(id) {
if (document.getElementById("price_netto" + id).value != "") {
change_brutto(id);
} else if (document.getElementById("price_brutto" + id).value != "") {
change_netto(id);
}
}
function count_changed(id) {
var count = replace_dots(document.getElementById("count" + id));
var brutto = replace_dots(document.getElementById("price_brutto" + id));
var summ = document.getElementsByName("summary_entity[]");
document.getElementById("summary" + id).value = brutto * count;
for (var i = 0; i < summ.length; i++) {
var val = summ[i];
price_summary += parseFloat(val.value);
}
document.getElementById("summary").innerHTML = price_summary;
}
function summary() {
}
window.onload = function() {
var btn = document.getElementById("add_product");
btn.addEventListener("click", function() {
id_count += 1;
document.getElementById("products_table").innerHTML +=
"<tr id='" + id_count + "'>\
<td><input type='text' class='form-control' name='name' id='name" + id_count + "' placeholder='Nazwa produktu'></td>\
<td><input type='number' class='form-control' onchange='count_changed(" + id_count + ")' name='count' id='count" + id_count + "' value='1' placeholder='Liczba produktów'></td>\
<td><input type='text' class='form-control' onchange='change_brutto(" + id_count + ")' name='price_netto' id='price_netto" + id_count + "' oninput='netto_changed()' value='0.00' placeholder='Cena netto'></td>\
<td class='input-group'><input type='text' class='form-control' onchange='vat_changed(" + id_count + ")' name='vat_rate' id='vat_rate" + id_count + "' value='23' placeholder='Stawka VAT'>\
<span class='input-group-addon'>%</span>\
</td>\
<td><input type='text' class='form-control' name='price_brutto' id='price_brutto" + id_count + "' oninput='brutto_changed()' value='0.00' placeholder='Stawka brutto'></td>\
<td><input type='text' class='form-control' name='summary_entity[]' id='summary" + id_count + "' value='0.00' readonly></td>\
<td><button type='button' onclick='delete_product(" + id_count + ")' class='btn btn-alert'>Usuń</button></td>\
</tr>";
}, false);
}
<table id="products_table" class="table table-bordered">
<tr>
<th>Nazwa produktu</th>
<th style="width: 7%;">Liczba produktów</th>
<th style="width: 10%;">Cena jednostkowa netto</th>
<th style="width: 10%;">Stawka VAT</th>
<th style="width: 10%;">Cena jednostkowa brutto</th>
<th style="width: 10%;">Wartość końcowa brutto</th>
<th style="width: 10%;">Akcje</th>
</tr>
<tr id="1">
<td><input type="text" class="form-control" name="name" id="name1" placeholder="Nazwa produktu"></td>
<td><input type="number" class="form-control" onchange="count_changed(1)" name="count" id="count1" value="1" placeholder="Liczba produktów"></td>
<td><input type="text" class="form-control" onchange="change_brutto(1)" name="price_netto" id="price_netto1" value="0.00" placeholder="Cena netto"></td>
<td class="input-group"><input type="text" class="form-control" onchange="vat_changed(1)" name="vat_rate" id="vat_rate1" value="23" placeholder="Stawka VAT">
<span class="input-group-addon">%</span>
</td>
<td><input type="text" class="form-control" onchange="change_netto(1)" name="price_brutto" id="price_brutto1" value="0.00" placeholder="Cena brutto"></td>
<td><input type="text" class="form-control" name="summary_entity[]" id="summary1" value="0.00" readonly></td>
<td><button type="button" onclick="delete_product(1)" class="btn btn-alert">Usuń</button></td>
</tr>
</table>
<table class="table table-bordered">
<tr>
<td style="width: 60%; text-align: right;">Razem do zapłaty: </td>
<td style="text-align: left;" name="summary" id="summary"></td>
</tr>
</table>
<button type="button" id="add_product" class="btn btn-success">Dodaj produkt</button>
The problem is:
your <tr> tags must be put inside <tbody>. Because you are missing it, so whenever you add a new <tr>, new <tbody> will automatically added and warpped around the <tr>. But one <table>, only have 1 <tbody>, adding more than 1 causing the entire table to reload.
Solution:
Create a <tbody> tag inside your table, give it an ID.
Whenever you want to insert new row, insert into that <tbody> instead
<table>
<tbody id="products_table">
</tbody>
</table>
Leo's answer is probably the best you should do, but I found an other way.
I used the insertRow and insertCell functions that append things without reloading the table.
Here's a working example (you can run it using the run code snippet at the bottom):
var id_count = 1;
var price_summary = 0;
function delete_product(id) {
document.getElementById(id).remove();
}
function change_brutto(id) {
var netto = replace_dots(document.getElementById('price_netto' + id));
var vat = replace_dots(document.getElementById('vat_rate' + id));
var count = replace_dots(document.getElementById('count' + id));
if (vat > 0) {
vat = vat / 100;
vat += 1;
var calc = netto * vat;
document.getElementById('price_brutto' + id).value =
Math.round((calc + Number.EPSILON) * 100) / 100;
calc = calc * count;
document.getElementById('summary' + id).value =
Math.round((calc + Number.EPSILON) * 100) / 100;
} else if (vat == '' || vat == 0) {
document.getElementById('vat_rate' + id).value = '0';
document.getElementById('price_brutto' + id).value = netto;
document.getElementById('summary' + id).value = netto * count;
} else {
alert('Wpisz poprawną stawkę VAT');
}
}
function change_netto(id) {
var brutto = replace_dots(document.getElementById('price_brutto' + id));
var vat = replace_dots(document.getElementById('vat_rate' + id));
if (vat > 0) {
vat = vat / 100;
vat += 1;
var calc = brutto / vat;
document.getElementById('price_netto' + id).value =
Math.round((calc + Number.EPSILON) * 100) / 100;
} else if (vat == '' || vat == 0) {
document.getElementById('vat_rate' + id).value = '0';
document.getElementById('price_netto' + id).value = brutto;
} else {
alert('Wpisz poprawną stawkę VAT');
}
}
function replace_dots(string) {
newString = string.value.replace(',', '.');
return newString;
}
function vat_changed(id) {
if (document.getElementById('price_netto' + id).value != '') {
change_brutto(id);
} else if (document.getElementById('price_brutto' + id).value != '') {
change_netto(id);
}
}
function count_changed(id) {
var count = replace_dots(document.getElementById('count' + id));
var brutto = replace_dots(document.getElementById('price_brutto' + id));
var summ = document.getElementsByName('summary_entity[]');
document.getElementById('summary' + id).value = brutto * count;
for (var i = 0; i < summ.length; i++) {
var val = summ[i];
price_summary += parseFloat(val.value);
}
document.getElementById('summary').innerHTML = price_summary;
}
function summary() {}
window.onload = function () {
var btn = document.getElementById('add_product');
btn.addEventListener(
'click',
function () {
id_count += 1;
let table = document.getElementById('products_table');
let row = table.insertRow();
row.id = id_count;
let cell0 = row.insertCell();
cell0.innerHTML =
"<td><input type='text' class='form-control' name='name' id='name" +
id_count +
"' placeholder='Nazwa produktu'></td>";
let cell1 = row.insertCell();
cell1.innerHTML =
"<td><input type='number' class='form-control' onchange='count_changed(" +
id_count +
")' name='count' id='count" +
id_count +
"' value='1' placeholder='Liczba produktów'></td>";
let cell2 = row.insertCell();
cell2.innerHTML =
"<td><input type='text' class='form-control' onchange='change_brutto(" +
id_count +
")' name='price_netto' id='price_netto" +
id_count +
"' oninput='netto_changed()' value='0.00' placeholder='Cena netto'></td>";
let cell3 = row.insertCell();
cell3.innerHTML =
"<td class='input-group'><input type='text' class='form-control' onchange='vat_changed(" +
id_count +
")' name='vat_rate' id='vat_rate" +
id_count +
"' value='23' placeholder='Stawka VAT'><span class='input-group-addon'>%</span></td>";
let cell4 = row.insertCell();
cell4.innerHTML =
"<td><input type='text' class='form-control' name='price_brutto' id='price_brutto" +
id_count +
"' oninput='brutto_changed()' value='0.00' placeholder='Stawka brutto'></td>";
let cell5 = row.insertCell();
cell5.innerHTML =
"<td><input type='text' class='form-control' name='summary_entity[]' id='summary" +
id_count +
"' value='0.00' readonly></td>";
let cell6 = row.insertCell();
cell6.innerHTML =
"<td><button type='button' onclick='delete_product(" +
id_count +
")' class='btn btn-alert'>Usuń</button></td>";
},
false
);
};
<!doctype html>
<html>
<head>
<link rel="stylesheet" href="lib/style.css">
<script src="lib/script.js"></script>
</head>
<body>
<table id="products_table" class="table table-bordered">
<tr>
<th >Nazwa produktu</th>
<th style="width: 7%;">Liczba produktów</th>
<th style="width: 10%;">Cena jednostkowa netto</th>
<th style="width: 10%;">Stawka VAT</th>
<th style="width: 10%;">Cena jednostkowa brutto</th>
<th style="width: 10%;">Wartość końcowa brutto</th>
<th style="width: 10%;">Akcje</th>
</tr>
<tr id="1">
<td><input type="text" class="form-control" name="name" id="name1" placeholder="Nazwa produktu"></td>
<td><input type="number" class="form-control" onchange="count_changed(1)" name="count" id="count1" value="1" placeholder="Liczba produktów"></td>
<td><input type="text" class="form-control" onchange="change_brutto(1)" name="price_netto" id="price_netto1" value="0.00" placeholder="Cena netto"></td>
<td class="input-group"><input type="text" class="form-control" onchange="vat_changed(1)" name="vat_rate" id="vat_rate1" value="23" placeholder="Stawka VAT">
<span class="input-group-addon">%</span>
</td>
<td><input type="text" class="form-control" onchange="change_netto(1)" name="price_brutto" id="price_brutto1" value="0.00" placeholder="Cena brutto"></td>
<td><input type="text" class="form-control" name="summary_entity[]" id="summary1" value="0.00" readonly></td>
<td><button type="button" onclick="delete_product(1)" class="btn btn-alert">Usuń</button></td>
</tr>
</table>
<table class="table table-bordered">
<tr>
<td style="width: 60%; text-align: right;">Razem do zapłaty: </td>
<td style="text-align: left;" name="summary" id="summary"></td>
</tr>
</table>
<button type="button" id="add_product" class="btn btn-success">Dodaj produkt</button>
</body>
</html>
i want multiple text inputs that when i change one of them i want others to change with the same value too . my inputs are generating in a loop of v-for like below :
<tbody>
<variant-item v-for='(variant, index) in variants' :variant="variant" :key="index" :index="index" "></variant-item>
</tbody>
and here the input is getting generated :
<td>
<div class="control-group" :class="[errors.has(variantInputName + '[price]') ? 'has-error' : '']">
<input type="number" v-model="variant.price" :name="[variantInputName + '[price]']" />
<span class="control-error" v-if="errors.has(variantInputName + '[price]')">#{{ errors.first(variantInputName + '[price]') }}</span></div>
</td>
so with this code if i have 2 products for example the result would be like below :
<td><div class="control-group"><input type="number" name="variants[4344][price]" data-vv-as=""price"" step="any" class="control"> <!----></div></td>
.
.
.
.
<td><div class="control-group"><input type="number" name="variants[4345][price]" data-vv-as=""[price"" > <!----></div></td>
now I want this 2 or multiple inputs change together .
#section('css')
#parent
<style>
.table th.price, .table th.weight {
width: 100px;
}
.table th.actions {
width: 85px;
}
.table td.actions .icon {
margin-top: 8px;
}
.table td.actions .icon.pencil-lg-icon {
margin-right: 10px;
}
</style>
#stop
{!! view_render_event('bagisto.admin.catalog.product.edit_form_accordian.variations.before', ['product' => $product]) !!}
<accordian :title="'{{ __('admin::app.catalog.products.variations') }}'" :active="true">
<div slot="body">
{!! view_render_event('bagisto.admin.catalog.product.edit_form_accordian.variations.controls.before', ['product' => $product]) !!}
<button type="button" class="btn btn-md btn-primary" #click="showModal('addVariant')">
{{ __('admin::app.catalog.products.add-variant-btn-title') }}
</button>
<variant-list></variant-list>
{!! view_render_event('bagisto.admin.catalog.product.edit_form_accordian.variations.controls.after', ['product' => $product]) !!}
</div>
</accordian>
{!! view_render_event('bagisto.admin.catalog.product.edit_form_accordian.variations.after', ['product' => $product]) !!}
<modal id="addVariant" :is-open="modalIds.addVariant">
<h3 slot="header">{{ __('admin::app.catalog.products.add-variant-title') }}</h3>
<div slot="body">
<variant-form></variant-form>
</div>
</modal>
#push('scripts')
#parent
<script type="text/x-template" id="variant-form-template">
<form method="POST" action="{{ route('admin.catalog.products.store') }}" data-vv-scope="add-variant-form" #submit.prevent="addVariant('add-variant-form')">
<div class="page-content">
<div class="form-container">
<div v-for='(attribute, index) in super_attributes' class="control-group" :class="[errors.has('add-variant-form.' + attribute.code) ? 'has-error' : '']">
<label :for="attribute.code" class="required">#{{ attribute.admin_name }}</label>
<select v-validate="'required'" v-model="variant[attribute.code]" class="control" :id="attribute.code" :name="attribute.code" :data-vv-as="'"' + attribute.admin_name + '"'">
<option v-for='(option, index) in attribute.options' :value="option.id">#{{ option.admin_name }}</option>
</select>
<span class="control-error" v-if="errors.has('add-variant-form.' + attribute.code)">#{{ errors.first('add-variant-form.' + attribute.code) }}</span>
</div>
<button type="submit" class="btn btn-lg btn-primary">
{{ __('admin::app.catalog.products.add-variant-title') }}
</button>
</div>
</div>
</form>
</script>
<script type="text/x-template" id="variant-list-template">
<div class="table" style="margin-top: 20px; overflow-x: auto;">
<table>
<thead>
<tr>
<th class="sku">{{ __('admin::app.catalog.products.sku') }}</th>
<th>{{ __('admin::app.catalog.products.name') }}</th>
#foreach ($product->super_attributes as $attribute)
<th class="{{ $attribute->code }}" style="width: 150px">{{ $attribute->admin_name }}</th>
#endforeach
<th class="qty">{{ __('admin::app.catalog.products.qty') }}</th>
<th class="price">{{ __('admin::app.catalog.products.price') }}</th>
<th class="weight">{{ __('admin::app.catalog.products.weight') }}</th>
<th class="status">{{ __('admin::app.catalog.products.status') }}</th>
<th class="actions"></th>
</tr>
</thead>
<tbody>
<variant-item v-for='(variant, index) in variants' :variant="variant" :key="index" :index="index" :variant-price.sync="variantPrice" #onRemoveVariant="removeVariant($event)"></variant-item>
</tbody>
</table>
</div>
</script>
<script type="text/x-template" id="variant-item-template">
<tr>
<td>
<div class="control-group" :class="[errors.has(variantInputName + '[sku]') ? 'has-error' : '']">
<input type="text" v-validate="'required'" v-model="variant.sku" :name="[variantInputName + '[sku]']" class="control" data-vv-as=""{{ __('admin::app.catalog.products.sku') }}"" v-slugify/>
<span class="control-error" v-if="errors.has(variantInputName + '[sku]')">#{{ errors.first(variantInputName + '[sku]') }}</span>
</div>
</td>
<td>
<div class="control-group" :class="[errors.has(variantInputName + '[name]') ? 'has-error' : '']">
<input type="text" v-validate="'required'" v-model="variant.name" :name="[variantInputName + '[name]']" class="control" data-vv-as=""{{ __('admin::app.catalog.products.name') }}""/>
<span class="control-error" v-if="errors.has(variantInputName + '[name]')">#{{ errors.first(variantInputName + '[name]') }}</span>
</div>
</td>
<td v-for='(attribute, index) in superAttributes'>
<div class="control-group">
<input type="hidden" :name="[variantInputName + '[' + attribute.code + ']']" :value="variant[attribute.code]"/>
<input type="text" class="control" :value="optionName(variant[attribute.code])" readonly/>
</div>
</td>
<td>
<button style="width: 100%;" type="button" class="dropdown-btn dropdown-toggle">
#{{ totalQty }}
<i class="icon arrow-down-icon"></i>
</button>
<div class="dropdown-list">
<div class="dropdown-container">
<ul>
<li v-for='(inventorySource, index) in inventorySources'>
<div class="control-group" :class="[errors.has(variantInputName + '[inventories][' + inventorySource.id + ']') ? 'has-error' : '']">
<label>#{{ inventorySource.name }}</label>
<input type="text" v-validate="'numeric|min:0'" :name="[variantInputName + '[inventories][' + inventorySource.id + ']']" v-model="inventories[inventorySource.id]" class="control" v-on:keyup="updateTotalQty()" :data-vv-as="'"' + inventorySource.name + '"'"/>
<span class="control-error" v-if="errors.has(variantInputName + '[inventories][' + inventorySource.id + ']')">#{{ errors.first(variantInputName + '[inventories][' + inventorySource.id + ']') }}</span>
</div>
</li>
</ul>
</div>
</div>
</td>
<td>
<div class="control-group" :class="[errors.has(variantInputName + '[price]') ? 'has-error' : '']">
<input type="number" v-validate="'required|min_value:0.0001'" v-model="variant.price" :name="[variantInputName + '[price]']" class="control" data-vv-as=""{{ __('admin::app.catalog.products.price') }}"" step="any"/>
<span class="control-error" v-if="errors.has(variantInputName + '[price]')">#{{ errors.first(variantInputName + '[price]') }}</span>
</div>
</td>
<td>
<div class="control-group" :class="[errors.has(variantInputName + '[weight]') ? 'has-error' : '']">
<input type="number" v-validate="'required|min_value:0.0001'" v-model="variant.weight" :name="[variantInputName + '[weight]']" class="control" data-vv-as=""{{ __('admin::app.catalog.products.weight') }}"" step="any"/>
<span class="control-error" v-if="errors.has(variantInputName + '[weight]')">#{{ errors.first(variantInputName + '[weight]') }}</span>
</div>
</td>
<td>
<div class="control-group">
<select type="text" v-model="variant.status" :name="[variantInputName + '[status]']" class="control">
<option value="1" :selected="variant.status">{{ __('admin::app.catalog.products.enabled') }}</option>
<option value="0" :selected="!variant.status">{{ __('admin::app.catalog.products.disabled') }}</option>
</select>
</div>
</td>
<td class="actions">
<a :href="['{{ route('admin.catalog.products.index') }}/edit/' + variant.id]"><i class="icon pencil-lg-icon"></i></a>
<i class="icon remove-icon" #click="removeVariant()"></i>
</td>
</tr>
</script>
<script>
$(document).ready(function () {
Vue.config.ignoredElements = [
'variant-form',
'variant-list',
'variant-item'
];
});
var super_attributes = #json(app('\Webkul\Product\Repositories\ProductRepository')->getSuperAttributes($product));
var variants = #json($product->variants);
Vue.component('variant-form', {
data: function() {
return {
variant: {},
super_attributes: super_attributes
}
},
template: '#variant-form-template',
created: function () {
this.resetModel();
},
methods: {
addVariant: function (formScope) {
this.$validator.validateAll(formScope).then((result) => {
if (result) {
var this_this = this;
var filteredVariants = variants.filter(function(variant) {
var matchCount = 0;
for (var key in this_this.variant) {
if (variant[key] == this_this.variant[key]) {
matchCount++;
}
}
return matchCount == this_this.super_attributes.length;
})
if (filteredVariants.length) {
this.$parent.closeModal();
window.flashMessages = [{'type': 'alert-error', 'message': "{{ __('admin::app.catalog.products.variant-already-exist-message') }}" }];
this.$root.addFlashMessages()
} else {
var optionIds = [];
for (var key in this_this.variant) {
optionIds.push(this_this.variant[key]);
}
variants.push(Object.assign({
sku: '{{ $product->sku }}' + '-variant-' + optionIds.join('-'),
name: '',
price: 0,
weight: 0,
status: 1
}, this.variant));
this.resetModel();
this.$parent.closeModal();
}
}
});
},
resetModel: function () {
var this_this = this;
this.super_attributes.forEach(function(attribute) {
this_this.variant[attribute.code] = '';
})
}
}
});
Vue.component('variant-list', {
template: '#variant-list-template',
inject: ['$validator'],
data: function() {
return {
variants: variants,
variantPrice:0,
old_variants: #json(old('variants')),
superAttributes: super_attributes
}
},
created: function () {
var index = 0;
for (var key in this.old_variants) {
var variant = this.old_variants[key];
if (key.indexOf('variant_') !== -1) {
var inventories = [];
for (var inventorySourceId in variant['inventories']) {
inventories.push({'qty': variant['inventories'][inventorySourceId], 'inventory_source_id': inventorySourceId})
}
variant['inventories'] = inventories;
variants.push(variant);
} else {
for (var code in variant) {
if (code != 'inventories') {
variants[index][code] = variant[code];
} else {
variants[index][code] = [];
for (var inventorySourceId in variant[code]) {
variants[index][code].push({'qty': variant[code][inventorySourceId], 'inventory_source_id': inventorySourceId})
}
}
}
}
index++;
}
},
methods: {
removeVariant: function(variant) {
let index = this.variants.indexOf(variant)
this.variants.splice(index, 1)
},
}
});
Vue.component('variant-item', {
template: '#variant-item-template',
props: ['variantPrice','index', 'variant'],
inject: ['$validator'],
data: function() {
return {
inventorySources: #json($inventorySources),
inventories: {},
totalQty: 0,
superAttributes: super_attributes
}
},
created: function () {
var this_this = this;
this.inventorySources.forEach(function(inventorySource) {
this_this.inventories[inventorySource.id] = this_this.sourceInventoryQty(inventorySource.id)
this_this.totalQty += parseInt(this_this.inventories[inventorySource.id]);
})
},
computed: {
variantInputName: function () {
if (this.variant.id)
return "variants[" + this.variant.id + "]";
return "variants[variant_" + this.index + "]";
}
},
methods: {
removeVariant: function () {
this.$emit('onRemoveVariant', this.variant)
},
onVariantPriceInput(event) {
this.$emit('update:variantPrice', Number(event.target.value));
},
optionName: function (optionId) {
var optionName = '';
this.superAttributes.forEach(function(attribute) {
attribute.options.forEach(function(option) {
if (optionId == option.id) {
optionName = option.admin_name;
}
});
})
return optionName;
},
sourceInventoryQty: function (inventorySourceId) {
if (! Array.isArray(this.variant.inventories))
return 0;
var inventories = this.variant.inventories.filter(function(inventory) {
return inventorySourceId === parseInt(inventory.inventory_source_id);
})
if (inventories.length)
return inventories[0]['qty'];
return 0;
},
updateTotalQty: function () {
this.totalQty = 0;
for (var key in this.inventories) {
this.totalQty += parseInt(this.inventories[key]);
}
}
}
});
</script>
#endpush
If it is your objective to have a single price which is shared by all variants, then I would advise against having a price property per variant Object. variant.price suggests a price per variant. I would create a separate data property, say variantPrice that would be passed to each instance of the variant-item component.
(As an aside: If there is a single price that is to be shared by all variant-item components then it may be confusing to your users that you render a price input field per variant-item instead of having a single input field.)
One way to synchronize a value with multiple child components, and assuming you are using a version of Vue >= 2.3 and < 3, is to use the .sync modifier.
Your parent component - the one that references the variants Array - would have a new data property for variantPrice. Here is an example where the parent is the root Vue component:
new Vue({
components: {
variantItem: VariantItem
},
data() {
return {
variantPrice: 0,
variants: [
{
inputName: 'VariantOne'
},
{
inputName: 'VariantTwo'
}
]
};
},
el: "#App"
});
The template of the parent (root) would pass variantPrice as a prop to each variant-item instance using the .sync modifier which will bind the value of variantPrice to the update:variantPrice event emitted by the child. The template would look like:
<div id="App">
<variant-item v-for="(variant, index) in variants" :key="index" :variant="variant" :variant-price.sync="variantPrice"></variant-item>
</div>
Next, we must ensure that our VariantItem component takes a variantPrice as a prop and emits the update:variantPrice event when the input field is modified by the user:
const VariantItem = Vue.component('variant-item', {
methods: {
onVariantPriceInput(event) {
this.$emit('update:variantPrice', Number(event.target.value));
}
},
props: {
variant: {
required: true,
type: Object
},
variantPrice: {
required: true,
type: Number
}
},
template: '#VariantItemTemplate'
});
The template for this component would become:
<div>
<label :for="variant.inputName">{{ variant.inputName }}</label>
<input :id="variant.inputName" :name="variant.inputName" :value="variantPrice" #input="onVariantPriceInput" type="number">
</div>
I have created a fiddle for your reference.
My script is working fine on everything except internet explorer. I'm not sure if it because I am using unsupported syntax or functions or what but if someone could take a look and see if anything stands out to them it would be really appreciated.
The basic implementation of the script is to create a simple shopping cart list when users click on a button. The total increments to include the added item and the item name, quantity and price is listed.
I have other scripts that work on my page so I know it is possible to implement onclick for example but I am unsure how to proceed here.
<div class="product-div" id="big-blue-barrel-div">
<h3>Big Blue barrel- $199</h3>
<div class="img-div">
<img src="images/barrel-pic.png" alt="picture of barrel" class="product-img">
</div>
<span>Quantity: </span>
<input class="qty bigBlueBarrelQty" type="number" name="qty" value="1" min="1" id="bigBlueBarrelQty">
<button type="button" onclick="addData(this.id, 'bigBlueBarrelQty')" name="button" id="bigBlueBarrel">Add to Cart</button>
</div>
var values = {
bigBlueBarrel: {
name: "Big Blue Barrel",
price: 199
},
bigBlueBox: {
name: "Big Blue Box",
price: 399
},
babyBlueBarrel: {
name: "Baby Blue Barrel",
price: 99
}
}
var total = 0;
var rowCount = 1;
function addData(clicked_id, quantity) {
var price = values[clicked_id].price;
var qty = document.getElementById(quantity).value;
var lineTotal = price * qty;
total += lineTotal;
document.getElementById("total").innerHTML = total;
addRow(clicked_id, qty, lineTotal);
if (qty == 1) {
alert(`${qty} ${values[clicked_id].name} has been added to your cart!
Scroll down to view your cart.`)
} else if (qty > 1) {
alert(`${qty} ${values[clicked_id].name}s have been added to your cart!
Scroll down to view your cart`);
}
}
function addRow(clicked_id, qty, lineTotal) {
var rows = "";
if (rowCount % 2 != 0 ) {
rows += `<tr class="odd"><td>${values[clicked_id].name}</td><td class="row-qty">${qty}</td><td>$${lineTotal}</td><td class="delete"><button onclick="deleteRow(this)" class="delete-btn">delete</button></td></tr>`;
$(rows).appendTo("#cart tbody");
rowCount++;
} else {
rows += `<tr class="even"><td>${values[clicked_id].name}</td><td class="row-qty">${qty}</td><td>$${lineTotal}</td><td class="delete"><button onclick="deleteRow(this)" class="delete-btn">delete</button></td></tr>`;
$(rows).appendTo("#cart tbody");
rowCount++;
}
}
function deleteRow(r) {
var i = r.parentNode.parentNode.rowIndex;
document.getElementById("cart").deleteRow(i);
}
Any thoughts would be appreciated.
A lot of features in ES6 will not work in IE.
Template literals for example:
${qty} ${values[clicked_id].name}
In this case you need to rewrite your template literals into normal strings using quotes:
alert(qty + " " + values[clicked_id].name + " has been added to your cart!"+
"\n\n" +
"Scroll down to view your cart.");
This website:
https://caniuse.com/#search=template%20literals
and MDN are valuable resources when I comes to compatibility.
Rewrite:
Tested on IE and it works!
var values = {
bigBlueBarrel: {
name: "Big Blue Barrel",
price: 199
},
bigBlueBox: {
name: "Big Blue Box",
price: 399
},
babyBlueBarrel: {
name: "Baby Blue Barrel",
price: 99
}
}
var total = 0;
var rowCount = 1;
function addData(clicked_id, quantity) {
var price = values[clicked_id].price;
var qty = document.getElementById(quantity).value;
var lineTotal = price * qty;
total += lineTotal;
document.getElementById("total").innerHTML = total;
addRow(clicked_id, qty, lineTotal);
if (qty == 1) {
/*alert(`${qty} ${values[clicked_id].name} has been added to your cart!
Scroll down to view your cart.`)*/
alert(qty + " " + values[clicked_id].name + " has been added to your cart!" +
"\n\n" +
"Scroll down to view your cart.");
} else if (qty > 1) {
/*alert(`${qty} ${values[clicked_id].name}s have been added to your cart!
Scroll down to view your cart`);*/
alert(qty + " " + values[clicked_id].name + "s has been added to your cart!" +
"\n\n" +
"Scroll down to view your cart.");
}
}
function addRow(clicked_id, qty, lineTotal) {
var rows = "";
//optimizing this:
/*rows += `<tr class="odd"><td>${values[clicked_id].name}</td><td class="row-qty">${qty}</td><td>$${lineTotal}</td><td class="delete"><button onclick="deleteRow(this)" class="delete-btn">delete</button></td></tr>`;*/
rows += '<tr class="' + (rowCount % 2 ? 'even' : 'odd') + '"><td>' + values[clicked_id].name + '</td><td class="row-qty">' + qty + '</td><td>' + lineTotal + '</td><td class="delete"><button onclick="deleteRow(this)" class="delete-btn">delete</button></td></tr>';
$(rows).appendTo("#cart tbody");
rowCount++;
}
function deleteRow(r) {
var i = r.parentNode.parentNode.rowIndex;
document.getElementById("cart").deleteRow(i);
}
table#cart {
margin: 40px;
border: 1px solid #e3e3e3;
border-collapse: collapse;
}
table#cart td {
padding: 10px;
border-right: 1px dashed #f2f2f2;
}
table#cart td > button{
padding: 10px;
border: 1px solid #f2f2f2;
background-color: #ff4444;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="product-div" id="big-blue-barrel-div">
<h3>Big Blue barrel- $199</h3>
<div class="img-div">
<img src="images/barrel-pic.png" alt="picture of barrel" class="product-img">
</div>
<span>Quantity: </span>
<input class="qty bigBlueBarrelQty" type="number" name="qty" value="1" min="1" id="bigBlueBarrelQty">
<button type="button" onclick="addData(this.id, 'bigBlueBarrelQty')" name="button" id="bigBlueBarrel">Add to Cart</button>
</div>
<!-- added for testing -->
<table id="cart">
<tbody>
</tbody>
</table>
Total: <span id="total"></span>
For creating table I am using ng-repeat to render table row. onchange of dropdown I am calling a function which will run have some conditions on basis of that condition I am pushing an object to an array which bind to a scope variable.
My HTML
<div class="col-md-12" >
<div class="portlet light" >
<div class="portlet-title">
<div class="caption">Installment Structure </div>
</div>
<div class="portlet-body">
<div class="row">
<div class="col-md-12">
<table id="instalmentStructure" class="table table-bordered">
<tbody>
<tr>
<th style="width:20%;">From Installment
</th>
<th style="width:20%;">To Installment</th>
<th style="width:20%;">Installment Amount
</th>
<th style="width:20%;"></th>
</tr>
<tr class="quoteVal" ng-repeat="item in installmentLists">
<td >{{item.fromInst}}</td>
<td >{{item.toInst}}</td>
<td contenteditable="true" class="quoteVal">{{item.amtInst}}</td>
<td>
<span class="col-md-6">
<center>
<a ng-click="editRecord(item,$index)">
<i class="fa fa-pencil"></i>
</a>
</center>
</span>
<span class="col-md-6">
<center>
<a ng-click="deleteRecord(item,$index)">
<i class="fa fa-trash"></i>
</a>
</center>
</span>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
My Controller Code:
$scope.createInstallments = function () {
console.log("will create installments");
if (trialCalculCntrl.emiCalQde.bulletFreq == 12) {
console.log("Bullet Frequency is Yearly");
var bulletFreq = trialCalculCntrl.emiCalQde.bulletFreq;
$scope.installmentLists = [];
$scope.installmentObj = {
'fromInst': "",
'toInst': "",
'amtInst': ""
};
var remainder = tenure % 12;
if (remainder == 0) {
var numofrows = ((tenure * 2) / 12).toFixed(0);
for (var i = 1; i <= numofrows; i++) {
if (i == 1) {
$scope.installmentObj = {
'fromInst': i,
'toInst': bulletFreq - 1,
'amtInst': ""
};
$scope.installmentLists.push($scope.installmentObj);
} else if (i % 2 == 0) {
console.log("EVEN i: ", i);
var preval = $('tr.quoteVal').eq(i - 2).find('td:eq(1)').text();
console.log("Previous Val ", preval);
} else {
console.log("ODD i: ", i);
// var preval = $('tr.quoteVal').eq(i-1).find('td:eq(2)').text();
// console.log("Previous Val ",preval);
}
}
console.log("Instalment list : ", $scope.installmentLists);
} else {
var numofrows = (((tenure * 2) / 12) + 1).toFixed(0);
for (var i = 0; i < numofrows; i++) {
$scope.installmentObj = {
'fromInst': "",
'toInst': "",
'amtInst': ""
};
$scope.installmentLists.push($scope.installmentObj);
}
console.log("Instalment list : ", $scope.installmentLists);
}
}
};
Inside for loop after first run I am pushing the object to $scope.installmentLists array but it is not showing in to HTML so I am not able to read the array object in second run of for loop. I am using jQuery selectors to read, so console.log("Previous Val ", preval); gives me an empty string.
Place your jquery about console.log in setTimeout when changed $scope. Otherwise the jquery selector does not return expected because the HTML has not been rendered.
setTimeout(function() {
onsole.log("EVEN i: ", i);
var preval = $('tr.quoteVal').eq(i - 2).find('td:eq(1)').text();
console.log("Previous Val ", preval);
}, 500);
I'm try to align a table wich was generated by javascript, but I'already tried every thing and nothing work!
Note: I already try use display block on thead with text-align:center, already try to use display theader-goup too, align-text:center with a class for thead and th. But still doesn't work.
Can someone help me?
<div role="tabpanel" class="tab-pane" id="OrcamentoMaterial">
<div class="col-md-12">
<div class="page-header m-b-20" style="margin-top:-30px;">
<h2 class="m-b-10"><strong style="font-size:18px;">
<a style="color: red;">{{item.Codigo}} </a> - {{item.Descricao}}</strong></h2>
<div class="col-md-3">
<div class="fg-lin">
<label>Nome da pessoa que solicitou o orçamento</label>
<input id="txtPessoaSolicitouOrcamento" class="form-control fg-input" />
</div>
</div>
<div class="col-md-3" style="margin-top:-6px;">
<div class="fg-line">
<div class="select">
#Html.Label("Executor")
#Html.DropDownListFor(model => model.TecnicoId, Model.listaTecnicos, "Selecione", new { #id = "ddlPessoaExecutora", #style = "height:20px !important;", #class = "form-control " })
</div>
</div>
</div>
<div class="col-md-3">
<div class="fg-lin">
<label>Descrição</label>
<input id="txtDescricaoOrcamento" class="form-control fg-input" />
</div>
</div>
<div class="col-md-3">
<div class="fg-lin">
<label>Data orçamento</label>
<input type="datetime" id="txtDataOrcamento" class="form-control fg-input datepicker" />
</div>
</div>
</div>
<fieldset class="col-md-12 m-t-30 m-b-20">
<legend>ORÇAMENTO MATERIAL</legend>
<div class="row m-t-10">
<div class="form-group col-md-10 m-t-15">
<div class="fg-line">
<select id="selectMaterial" style="width:100%">
<text>
<option value="0" selected="selected"></option>
</text>
</select>
</div>
</div>
<div class="col-md-1 form-group fg-float m-t-10">
<div class="fg-line">
<label>Quantidade</label>
#Html.TextBoxFor(m => m.OrcamentoMaterial.QuantidadeMaterial, new { #class = "form-control fg-input", id = "txtMaterialQuantidade" })
</div>
#Html.ValidationMessageFor(o => o.Material.Nome, "", new { #class = "has-error text-danger" })
</div>
<div class="col-md-1">
<i class="zmdi zmdi-plus"></i>
</div>
</div>
<div class="row" style="font-size: smaller;">
</fieldset>
</div>
<table class="table table-striped" id="tableOrcamentoMaterial">
<thead align="center">
<tr>
<th>Material</th>
<th>Ni</th>
<th>Name</th>
<th>Qtd.</th>
<th>Value</th>
<th>Total</th>
</tr>
</thead>
<tbody class="tbFooterOrcamentoMaterial">
</tbody>
</table>
$("#btn-addOrcamentoMaterial").click(function ()
{
var solicitante = "";
var executor = "";
var descricaoOrcamento = "";
var TecnicoId = 0;
var dataOrcamento = "";
var material = "";
var qtdMaterial = "";
var valorTotal = 0;
var materialId = 0;
var codigoNi = "";
var codigoMaterial = "";
$("#ddlPessoaExecutora option:selected").val() != null ? TecnicoId = $("#ddlPessoaExecutora option:selected").val() : $("#ddlPessoaExecutora option:selected").val(0);
$("#txtPessoaSolicitouOrcamento").val() != null ? solicitante = $("#txtPessoaSolicitouOrcamento").val() : "Não informado";
$("#ddlPessoaExecutora option:selected").text() != "" ? executor = $("#ddlPessoaExecutora option:selected").text() : $("#ddlPessoaExecutora option:selected").val(1);
$("#txtDescricaoOrcamento").val() != null ? descricaoOrcamento = $("#txtDescricaoOrcamento").val() : "Não possui descrição";
$("#txtDataOrcamento").val() != null ? dataOrcamento = $("#txtDataOrcamento").val() : new Date();
$("#selectMaterial option:selected").text() != null ? material = $("#selectMaterial option:selected").text() : $("#selectMaterial option:selected").val(1);
$("#selectMaterial option:selected").val() != null ? materialId = $("#selectMaterial option:selected").val() : $("#selectMaterial option:selected").val(0);
$("#txtMaterialQuantidade").val() != null ? qtdMaterial = $("#txtMaterialQuantidade").val() : "0";
var qryMaterial = getMaterialbyId(materialId);
valor = qryMaterial.vlMaterial;
codigoNi = qryMaterial.CodigoNi;
codigoMaterial = qryMaterial.CodigoMaterial;
valorTotal = parseFloat(qtdMaterial) * valor;
var orcamentoExibir = codigoMaterial + "-" + codigoNi + "-" + material + "-" + qtdMaterial + "-" + valor + "-" + valorTotal;
orcamentoExibir = orcamentoExibir.split("-");
var orcamento = dataOrcamento + " - " + solicitante + " - " + executor + " - " + descricaoOrcamento + " - "+ codigoMaterial + "-" + codigoNi+ "-" + material + " - " + qtdMaterial + " - " + valor + " - " + valorTotal +" - " + TecnicoId +" - " + materialId;
incluirOrcamentoMaterial(orcamento, orcamentoExibir);
$("#ddlPessoaExecutora option:selected").val("");
$("#txtPessoaSolicitouOrcamento").val("");
$("#ddlPessoaExecutora option:selected").val(0);
$("#txtDescricaoOrcamento").val("");
$("#txtDataOrcamento").val("");
$("#selectMaterial option:selected").val(0);
$("#selectMaterial").text("");
$("#txtMaterialQuantidade").val("");
});
function incluirOrcamentoMaterial(orcamento, orcamentoExibir) {
listaOrcamentoMaterial.push(orcamento);
listaOrcamentoMaterialExibir.push(orcamentoExibir);
for (i = 0; i < listaOrcamentoMaterialExibir.length; i++) {
var tr = document.createElement('TR');
tr.class = 'rowOrcamentoMaterial';
i = listaOrcamentoMaterialExibir.length -1;
valorTotalOrcamento = valorTotalOrcamento + parseFloat(listaOrcamentoMaterialExibir[i][5]);
for (j = 0; j < listaOrcamentoMaterialExibir[i].length; j++) {
var td = document.createElement('TD');
td.appendChild(document.createTextNode(listaOrcamentoMaterialExibir[i][j]));
td.class = 'cellOrcamentoMaterial';
tr.appendChild(td)
}
$("#tableOrcamentoMaterial > tbody").append(tr);
}
$("#tableOrcamentoMaterial > tbody > tr").addClass("rowOrcamentoMaterial");
var tt = $(".rowOrcamentoMaterial").children.length;
debugger;
if(!$("#tableOrcamentoMaterial > tfoot .totalOrcamentoMaterial").html()){
$("#tableOrcamentoMaterial").append('<tfoot><tr><td colspan="5"></td><td class="totalOrcamentoMaterial orcamento" style="color:red;">'+ valorTotalOrcamento + '</td></tr></tfoot>');
} else
{
$("#tableOrcamentoMaterial > tfoot .totalOrcamentoMaterial").html(valorTotalOrcamento);
}
};
Put the table on a div element, then give the div a width and a margin for example
<div id="styleExample" style="width:920px; margin:auto">
<table id="yourTable"...></table>
</div>