I have a shopping basket where i want a user to be able to click on a button that takes them to a separate page whilst capturing their shopping basket contents (item names, quantities, prices, etc). At the moment i'm using localStorage to send just the item names to my new page however the only item that ever prints is the last item to be placed in a basket (i'm not sure how to stop localStorage overwriting data like it does).
This is the itemName section on the basket page.
<!--START: itemnamelink--><a id="itemName" href="product.asp?itemid=[ITEM_CATALOGID]">[ITEM_NAME]</a><!--END: itemnamelink-->
This is a script i have on my basket page.
jQuery( document ).ready(function($) {
var itemName = document.getElementById('itemName');
var arrayShop = [{name: itemName.textContent}];
if(localStorage.getItem("user") == null) {
localStorage.setItem("user",JSON.stringify([arrayShop]))
}
else{
var newArray = JSON.parse(localStorage.getItem("user"));
newArray.push(arrayShop);
localStorage.setItem("user", JSON.stringify(newArray))
}
});
This is the script on a new page
jQuery( document ).ready(function($) {
var hst = document.getElementById("add");
console.log(localStorage.getItem("user"));
var items = JSON.parse(localStorage.getItem("user"));
for (var i = 0; i < items.length; i++) {
hst.innerHTML += "<tr><td>" + items[i].name + "</td><td>"+ items[i].price +
"</td></tr>";
}
});
<!--HTML ON THE PAGE -->
<table id="add">
<tr><td>Name</td><td>Price</td></tr>
</table>
I'm getting the following output which is the last item in the basket (there's 4 items in the basket).
Name
110mm Chair
I should be getting.
Name
110mm Chair
Red Chair
Green Chair
Grey Chair
Below is my shopping cart
<div class="shoppingCartItems">
<div class="titles2">
<div class="item-info">[shoppingcart_items]</div>
<div class="item-qty">[shoppingcart_quantity]</div>
<div class="item-price">[shoppingcart_price]</div>
<div class="item-total">[shoppingcart_total]</div>
<div class="item-remove"> </div>
<div class="clear"></div>
</div>
<!--START: SHOPPING_CART_ITEM-->
<div class="row">
<div class="item-info">
<div class="product-image"><!--START: itemthumbnail--><img src="thumbnail.asp?file=[THUMBNAIL]" height="55" width="55" /><!--END: itemthumbnail--><!--START: thumbnailnolink--><img src="thumbnail.asp?file=[THUMBNAIL]" height="55" width="55" id="tnl" /><!--END: thumbnailnolink--></div>
<div class="product-name-options">
<!--START: itemnamelink--><a id="itemName" class ="itemName" href="product.asp?itemid=[ITEM_CATALOGID]">[ITEM_NAME]</a><!--END: itemnamelink-->
<!--START: itemnamenolink--><span id="spnItemName">[ITEM_NAME]</span><!--END: itemnamenolink-->
<!--START: itemoptions-->
<br />
View/Hide options<br />
<div id=opt[ITEM_ID] name=opt[ITEM_ID] style="display:none;">[OPTIONS]</div>
<!--END: itemoptions-->
<!--START: recurring_frequency-->
<div class="recurring_frequency">This item will Autoship every <strong>[recurring_frequency]</strong></div>
<!--END: recurring_frequency-->
<!--START: giftwraplink-->
<div class="giftwraplink"> <a onclick="showGiftWrap('[ITEM_ID]')">[giftwrap_link]</a> </div>
<!--END: giftwraplink--></div>
<div class="clear"></div>
</div>
<div class="item-qty">
<input type="text" name="qtyitemnum" value="[ITEM_QUANTITY]" size="3" maxlength="5" class="txtBoxStyle" />
<input type="hidden" name="coliditemnum" value="[ITEM_ID]" size="3" maxlength="5" />
[shoppingcart_updatecart]
</div>
<div class="item-price" id="itemPrice">[ITEM_PRICE] </div>
<div class="item-total">[ITEM_SUBTOTAL]</div>
<div class="item-remove"><i class="icon-cancel"></i></div>
<div class="clear"></div>
</div>
<!--END: SHOPPING_CART_ITEM-->
<div class="shoppingCartTotal">
<div class="clear"> </div>
<div class="item-total">[CARTSUBTOTAL]</div>
<div class="item-price">[shoppingcart_subtotal]</div>
<div class="clear"></div>
<!--START: DISCOUNTS-->
<div class="clear"> </div>
<div class="item-total">[DISCOUNTS]</div>
<div class="item-price">[checkout1_discounts]</div>
<div class="clear"></div>
<!--END: DISCOUNTS-->
<div class="clear"> </div>
<div class="item-total"><strong>[CARTTOTAL]</strong></div>
<div class="item-price"><strong>[shoppingcart_total]</strong></div>
<div class="clear"></div>
</div>
</div>
I am not getting your shopping cart properly how you are doing it.
but using below code as the reference you can solve your problem.
var uname = document.getElementById('uname1').value;
function checkFname(){
var fname = document.forms["form"]["fname"].value;
var chk_fname = fname.replace(/^[a-zA-z]{2,15}$/, '');
if (fname != chk_fname) {
document.getElementById("fname").className = '';
return true;
}
else if (fname == chk_fname) {
document.getElementById("fname").className = 'error';
return false;
}
}
function Register(){
var uname = document.getElementById('uname').value;
var user = {
'fname':document.getElementById('fname').value,
};
localStorage.setItem(uname,JSON.stringify(user));
}
function Validate(){
Register();
}
While inserting the data in local storage Register() function will take the username as key and user can be an array which can contain data.
That it is because you are overwriting, not adding. In your code you need to append elements to your storage, using your last record and adding the new one, like this:
var arrayShop = {name: 'Chair 2'};
if(localStorage.getItem("user") == null) {
localStorage.setItem("user",JSON.stringify([arrayShop]))
}
else{
var newArray = JSON.parse(localStorage.getItem("user"));
newArray.push(arrayShop);
localStorage.setItem("user", JSON.stringify(newArray))
}
In this example my 'Chair 1' is your new element to add, soo if you execute it two times it will add a new element that is what passed in arrayShop.
Related
I have an observable array that contains a list of object that I want to filter through based on a user input. If the user searches a word that appears in the array in two different places then the filter function should return the title of both objects and delete or hide all other objects in the array that did not match the input from the user. I must use knockout js to preform this feature which is still new to me. Currently my filter function checks to see if the user input is included in a title of one of the objects within the array and if it is not then it removes the object. However, this not providing me what I need as it does not accurately filter the list.
My ViewMode
var viewModel = function() {
var self = this;
self.filter = ko.observable('');
self.locationList = ko.observableArray(model);
self.filterList = function(){
return ko.utils.arrayFilter(self.locationList(), function(location) {
if(location.title == self.filter()){
return location.title
}
else if( location.title.includes(self.filter()) ){
return location.title
}
else{
return self.locationList.remove(location)
}
});
};
}
The View
<section class="col-lg-2 sidenav">
<div class="row">
<div class="col-lg-12">
<div class="input-group">
<input data-bind="textInput: filter"
type="text" class="form-control" placeholder="Filter Places"
aria-describedby="basic-addon2" id="test">
<button data-bind="click: filterList id="basic-addon2">
<i class="glyphicon glyphicon-filter"></i>
Filter
</button>
</div>
</div>
<div class="col-lg-12">
<hr>
<div data-bind="foreach: locationList">
<p data-bind="text: $data.title"></p>
</div>
</div>
</div>
</section>
The answer to the question can be found here answered by Viraj Bhosale
ViewModel
var viewModel = function() {
var self = this;
self.filter = ko.observable('');
self.locationList = ko.observableArray(model);
self.filterList = ko.computed(function(){
return self.locationList().filter(
function(location){
return (self.filter().length == 0 || location.title.toLowerCase().includes(self.filter().toLowerCase()));
}
);
});
}
View
<main class="container-fluid">
<div class="row">
<section class="col-lg-2 sidenav">
<div class="row">
<div class="col-lg-12">
<div class="input-group">
<input data-bind="textInput: filter, valueUpdate: 'keyup'"
type="text" class="form-control" placeholder="Filter Places"
aria-describedby="basic-addon2" id="test">
</div>
</div>
<div class="col-lg-12">
<hr>
<div data-bind="foreach: filterList">
<p data-bind="text: $data.title"></p>
</div>
</div>
</div>
</section>
<section class="col-lg-10" id="map"></section>
</div>
I have a view like this:
<div class="GridContainer">
<div>
<div class="row gridHeader">
<div class="small-9 columns">Member Name</div>
<div class="small-2 columns">Date Registered</div>
</div>
#foreach (var member in Model.Members)
{
<div class="row">
<div class="small-9 columns">#member.MemberName</a></div>
<div class="small-2 columns">#member.DateRegistered</div>
<input type="hidden" asp-for="#member.Id" />
<a id="btnMemberDelete" href="#">Delete</a>
</div>
}
</div>
my javascript:
<script type="text/javascript">
$(document).ready(function () {
$('#btnMemberDelete').click(function () {
var id = $(this).closest("div").find("input:hidden[name='member.Id']").val();
var url = '#Url.Action("DeleteMembers", "Member")' + "?id=" + id;
openMemberDialog(url);
});
});
</script>
The delete button only works for the very first row at the moment. If say I have 4 rows the other 3's delete button won't even register. It won't even open the dialog box. Is there something I'm missing here as the code seems to be correct to me.
Thanks!
Fiddle here
As answerd above you need to have a uniqe ID or use a class. in my solution above I use a class like so:
$(document).ready(function () {
$('.btnMemberDelete').click(function (e) {
e.preventDefault();
var id = $(this).closest("div").find("input:hidden[name='member.Id']").val();
console.log(id)
});
});
Also correct your html:
#foreach (var member in Model.Members)
{
<div class="row">
<div class="small-9 columns">#member.MemberName</a></div> // remove the '</a>' here
<div class="small-2 columns">#member.DateRegistered</div>
<input type="hidden" asp-for="#member.Id" />
<a class="btnMemberDelete" href="#">Delete</a>
</div>
}
You need to give a unique id for each delete button. Or you can give a classname instead of id to your anchor tag.
<div class="GridContainer">
<div>
<div class="row gridHeader">
<div class="small-9 columns">Member Name</div>
<div class="small-2 columns">Date Registered</div>
</div>
#foreach (var member in Model.Members)
{
<div class="row">
<div class="small-9 columns">#member.MemberName</a></div>
<div class="small-2 columns">#member.DateRegistered</div>
<input type="hidden" asp-for="#member.Id" />
<a class="btnMemberDelete" href="#">Delete</a>
</div>
}
</div>
<script type="text/javascript">
$(document).ready(function () {
$('.btnMemberDelete').click(function () {
var id = $(this).closest("div").find("input:hidden[name='member.Id']").val();
var url = '#Url.Action("DeleteMembers", "Member")' + "?id=" + id;
openMemberDialog(url);
});
});
</script>
I am working in ASP.Net MVC4. My div elements contents are generated in a loop as below:
#foreach (var product in Model.Products)
{
<div class="col-md-2 vcenter">
<span class="product-price">Preço: #Model.Price.ToString("C")</span>
</div>
#if (Model.IsValid != null && Model.IsValid != "")
{
<div class="col-md-2" style="text-align: end;">
<span>Enter number.</span>
</div>
<div class="col-md-2 vcenter" style="text-align: end;">
#Html.TextBoxFor(m => m.CouponTemp, new {
#class = "product-discount-coupon",
chart_price = Model.Price.ToString(),
dicsount_price = Model.SpecialPrice.ToString(),
product_coupon = Model.Coupon,
style = "width:50px;"
})
<button type="button" class="apply-discount">Recalculate</button>
</div>
}
}
JavaScript portion
$(".apply-discount").on("click", function () {
var applyCoupon = $(this).parent().find(".product-discount-coupon").val();
var price = $(this).parent().find(".product-price").val();
var cost = 0;
if (applyCoupon === NaN) {
applyCoupon = 0;
}
if (price === NaN) {
price = 0;
}
$(this).parent().find(".product-price").val(applyCoupon);
});
Browser generated html is below
<div>
<div class="col-md-1">
<img src="/Astrology/Product/GetImage/51da66b7-3cb9-418b-ae9a-bc9fe8073b26" style="width: 50px; height: 50px;" alt="Mapa Natal Cármico" />
</div>
<div class="col-md-6 vcenter">
<span style="font-size: large">Mapa Natal Cármico. Escrito por Marcelo Dalla</span>
</div>
<div class="col-md-2 vcenter">
<span class="product-price">Preço: R$ 44,00</span>
</div>
<div class="col-md-2 vcenter" style="text-align: end;">
<button type="button" class="dec-count">-</button>
<input chart-price="44,0000" class="product-count" data-val="true" data-val-number="The field Quantity must be a number." data-val-required="The Quantity field is required." dicsount-price="10,0000" id="products_7819060a-0f29-4637-83de-9262beb1a13f__Quantity" name="products[7819060a-0f29-4637-83de-9262beb1a13f].Quantity" product-coupon="10" readonly="readonly" style="width:50px;" type="text" value="1" />
<button type="button" class="inc-count">+</button>
</div>
<span>If you have a discount coupon for the purchase please enter it here and press the recalculate button.</span>
<div class="col-md-2 vcenter" style="text-align: end;">
<input chart-price="44,0000" class="product-discount-coupon" dicsount-price="10,0000" id="products_7819060a-0f29-4637-83de-9262beb1a13f__CouponTemp" name="products[7819060a-0f29-4637-83de-9262beb1a13f].CouponTemp" product-coupon="10" style="width:50px;" type="text" value="" />
<button type="button" class="apply-discount">Recalculate</button>
<input id="apply-product-coupon" type="hidden" name="apply-product-coupon">
</div>
<div class="col-md-1 vcenter">
<a href="/Astrology/Shop/DeleteFromCard?productId=41f7e40b-62ad-4202-964a-cbed7381b06c">
<i class="fa fa-remove"></i>
</a>
</div>
</div>
When the user clicks on the Recalculate button I want to put CouponTemp textbox value in another span. Note that clicking on block-1 does not impact on block-2 or rest, in the same way click on block-2 not impact on another block content.
<span>Preço: #Model.Price.ToString("C")</span>
Here is your script:
$(document).ready(function(){
$("button.apply-discount").click(function(){
//get your input value
var discount = $(this).prev('input.product-discount-coupon').first().val();
//Get your span
var resultSpan = $(this).parent().prev().prev().prev().find('span');
//Update your span with input value
resultSpan.html("Preço: R$ " + discount);
});
});
I create JSFiddle to show how it works.
Following code snippet may help you.
$(".apply-discount").on("click", function () {
var applyCoupon = $(this).parent().find(".product-discount-coupon");
var price = applyCoupon.val();
//to get others info
var chart_price= applyCoupon.attr('chart_price');
var dicsount_price= applyCoupon.attr('dicsount_price');
var product_coupon= applyCoupon.attr('product_coupon');
$(this).parent().prev().prev().find(".product-price").html('Preço: '+price*1);
});
N.B: price*1 will convert it to a number.
Well, pretty easy if you just assign ids to the elements. Use something like id from your product to ensure they are unique and match.
#foreach (var product in Model.Products)
{
<div class="col-md-2 vcenter">
<span>Preço: #Model.Price.ToString("C")</span>
</div>
#if (Model.IsValid != null && Model.IsValid != "")
{
<div class="col-md-2" style="text-align: end;">
<span id="#product.Id">Enter number.</span>
</div>
<div class="col-md-2 vcenter" style="text-align: end;">
#Html.TextBoxFor(m => m.CouponTemp, new {
#class = "product-discount-coupon",
chart_price = Model.Price.ToString(),
dicsount_price = Model.SpecialPrice.ToString(),
product_coupon = Model.Coupon,
style = "width:50px;",
id = "txt_" + #product.Id
})
<button type="button" class="apply-discount" onclick="adjustPrice(#product.Id);">Recalculate</button>
</div>
}
}
Then have a function that handles it:
<script type="text/javascript">
var adjustPrice = function (id) {
var txt = $('#txt_' + id).val();
$('#' + id).val(txt);
};
</script>
Have a form to create a contract, where that contract can have one or more users associated.
The area to input the users info, starts with only one field of one user, and one button to add more fields if needed.
<div id="utilizadores" class="row">
<div id="utilizador1" class="container-fluid">
<div class="row">
<div class="col-lg-5">
<input type="text" class="form-control" id="nomeUtilizador1" placeholder="Nome Utilizador">
</div>
<div class="col-lg-6">
<input type="text" class="form-control" id="funcaoUtilizador1" placeholder="Função">
</div>
</div>
</div>
</div>
This is the starting div
Clicking on Add User button it adds a new div under the "utilizador1"
<div id="utilizadores" class="row">
<div id="utilizador1" class="container-fluid">
<div class="row">
<div class="col-lg-5">
<input type="text" class="form-control" id="nomeUtilizador1" placeholder="Nome Utilizador">
</div>
<div class="col-lg-6">
<input type="text" class="form-control" id="funcaoUtilizador1" placeholder="Função">
</div>
</div>
</div>
<div id="utilizador2" class="container-fluid">
<div class="row">
<div class="col-lg-5">
<input type="text" class="form-control" id="nomeUtilizador2" placeholder="Nome Utilizador">
</div>
<div class="col-lg-6">
<input type="text" class="form-control" id="funcaoUtilizador2" placeholder="Função">
</div>
</div>
</div>
My question is, how can I get the number of users created, and insert them into a list using Javascript. The list will be a attribute of a Object (Contract).
What i have til now:
function test_saveItem() {
var contract = new Object();
contract.Dono = <% =uID %>;
contract.BoostMes = $("#boostMes").val();
contract.BoostAno = $("#boostAno").val();
var ListaUtilizadores = [];
var divs = document.getElementsByName("utilizador");
for (var i = 0; i < divs.length; i++){
var user = new Object();
user.Nome = $('#nomeUtilizador' + i).val();
ListaUtilizadores.push(user);
}
var test = JSON.stringify({ "contract": contract });
}
Any help appreciated
Edit: Got to a solution thanks to Shilly
List = [];
Array.prototype.slice.call(document.querySelectorAll('.user')).forEach(function (node, index) {
List.push({
"name" : document.getElementById('nameUser' + (index + 1)).value,
"job" : document.getElementById('jobUser' + (index + 1)).value
});
});
Something like this? But adding it into the addUser function as Super Hirnet says, will be more performant.
var divs = document.querySelector('#utilizadores').childNodes,
users = [];
Array.slice.call(divs).forEach(function (node, index) {
users.push({
"name" : divs[index].getElementById('nomeUtilizador' + (index + 1)).value
});
});
You can have an empty array and on every click of addUser put a new object into the array. The object can have information related to the added user.
I am developing shopping cart in codeigniter where I am fetching data from data base and when user clicks on add to cart the the data related to current item which is clicked by user get store in jQuery variables now I am facing problem that onclick event works only on first fetched item and on the rest it won't works and I am confuse why it's not working.
Here is my code.
<div class="col-md-9" >
<?php if(isset($products))
{
foreach($products as $row)
{
?>
<div class="row" >
<div class="col-md-4" id="con">
<div class="product">
<a href="products/<?=$row->sub_c_id?>/<?=$row->pid?>">
<img id="imgslct" alt="<?=$row->pname?>" height="173" width="144" src="<?php echo base_url(); ?>uploads/<?=$row->product_pic?>">
</a>
<div class="name">
<?=$row->pname?>
</div>
<div class="price">
<p id="price">price : <?=$row->pprice?></p>
<input type="hidden" id="pquan" value="<?=$row->pquantity;?>">
<button id="addtocart" class="btn btn-lg btn-default">Add to cart</button>
</div>
</div>
</div>
<?php
}
} ?>
Here is JQuery code.
<script type="text/javascript">
$(document).ready(function() {
var counter=0;
$("#con").on('click',function(){
counter++;
var pic=$(this).find("img").attr('src');
alert(pic);
var imgdata= $(this).find("#pname").text();
var productquantity= $('#pquan').val();
var productid=$('#pid').text();
var price=$("#price").text();
var qty="1";
var session_id="<?=$this->session->userdata('session_id');?>";
var pid="1";
$("#counter").text(counter);
var counting= $("#counter").text(counter);
<?php $counting=''?>+counting;
alert(counting);
<?php $new_data=array('counter' => $counting ) ?>
if(qty=="")
{
alert("no quantity added");
return false;
}
$.ajax({
type:"post",
url:"<?=base_url();?>temp_upload",
data:"pic="+pic+"&imgdata="+imgdata+"&productquantity="+productquantity+"&productid="+productid+"&price="+price+"&qty="+qty+"&session_id="+session_id+"&pid="+pid,
success: function(data)
{
alert(data);
$("#uploaded").html();
}
});
$("#newdata").append('<tr><td class="image"><img alt="IMAGE" class="img-responsive" src="'+pic+'"></td><td class="name">Black Dress</td><td class="quantity">x 3</td><td class="total">'+price+'</td><td class="remove"><img src="'+pic+'" alt="Remove" title="Remove"></td></tr>');
});
});
</script>
IDs should be unique.
The moment you change the id to a class (#con -> .con) and modify your code appropriatelly, they all will be selected.
See this example: http://jsfiddle.net/shomz/38PB2/
You are within a loop that is using the same id over and over with id="con" being the first. Since ids must be unique within the DOM, you need to change them from an id to a class.
You should do something like:
<div class="col-md-4 con">
<div class="product">
<a href="products/<?=$row->sub_c_id?>/<?=$row->pid?>">
<img class="imgslct" alt="<?=$row->pname?>" height="173" width="144" src="<?php echo base_url(); ?>uploads/<?=$row->product_pic?>">
</a>
<div class="name">
<?=$row->pname?>
</div>
<div class="price">
<p>price : <?=$row->pprice?></p>
<input type="hidden" class="pquan" value="<?=$row->pquantity;?>">
<button class="addtocart btn btn-lg btn-default">Add to cart</button>
</div>
</div>
</div>
Then change the beginning of your JavaScript to:
$(".con").on('click', function ()
{
counter++;
var $this = $(this);
var pic = $this.find("img").attr('src');
var imgdata = $this.find(".pname").text();
var productquantity = $this.find('.pquan').val();
var productid = $this.find('.pid').text();
var price = $this.find(".price").text();
var qty = "1";
var session_id = "<?=$this->session->userdata('session_id');?>";
var pid = "1";
first change the event to be attached to class not to id as id must be unique ,if you attach click event to id ,only the first element with that id will trigger that event
change
<div class="col-md-4" id="con">
to
<div class="col-md-4 con" >
also you have link tag inside that div which will make some problems till to stop propagation of that event
then to add click event to fetched elements you can use
$(document).on('click','.con',function(){
/// your code
});
so click event will be attached to the new elements too