I'm currently running an html and jQuery code that works but looks very ugly for me. I would really appreciate suggestion to do this more smarter.
Goal: update cells of a php generated table using an input field. Each cells contains a basic value which should be multiplied by the input.
Currently, I read the value of the input, take the basic value of each cell from an hidden input and rewrite the whole html of each cell ( hidden input + updated data).
Html code:
<table id='tbl'>
<thead>
<tr>
<th colspan="2">Quantity:
<input type="text" id="quantity" name="quantity" value="1">
</th>
</tr>
</thead>
<tbody>
<tr>
<td>
<input name="1_1" type="hidden" value="11"><span>11</span>
</td>
<td>
<input name="1_2" type="hidden" value="12"><span>12</span>
</td>
</tr>
<tr>
<td>
<input name="2_1" type="hidden" value="21">21
</td>
<td>
<input name="2_2" type="hidden" value="22">22
</td>
</tr>
<tr>
<td>
<input name="3_1" type="hidden" value="31">31
</td>
<td>
<input name="2_2" type="hidden" value="32">32
</td>
</tr>
</tbody>
</table>
Script:
$('#quantity').keyup(function () {
var quantity = parseFloat($(this).val());
if (quantity == "" || isNaN(quantity))
quantity = 1;
$('#tbl tbody tr td').map(function () {
var $row = $(this);
var $refvalue = $row.find(':input[type=hidden]').val();
var $refname = $row.find(':input[type=hidden]').attr('name');
$row.html('<input name="' + $refname + '" type="hidden" value="' + $refvalue + '">' + $refvalue * quantity);
});
});
Fiddle : http://jsfiddle.net/5KKrD/
Is there a better way to do ? I'm able to change both table, js and so on.
Regards
this is my approach - use data attribute (instead of a hidden input) to pass the multiplier, e.g.:
<td class="cell" data-value="11">11</td>
with this - you can grab the value very easily using jquery, e.g.:
$('.cell').data('value')
DEMO
I have refined your code a bit,its working smoothly
JS CODE:
$('#quantity').keyup(function () {
if ($(this).val()) {
var quantity = parseInt($(this).val());
if (quantity == "" || isNaN(quantity)) quantity = 1;
$('#tbl tbody tr td input').each(function () {
var row = $(this);
var mulVal = row.val() * quantity;
$(this).attr('value', mulVal);
$(this).parent().find('span').text(mulVal);
//var $refvalue = $row.find(':input[type=hidden]').val();
//var $refname = $row.find(':input[type=hidden]').attr( 'name' );
//$row.html( '<input name="'+ $refname +'" type="hidden" value="'+ $refvalue + '">' + $refvalue * quantity );
});
}
});
HTML CODE:
<table id='tbl'>
<thead>
<tr>
<th colspan="2">Quantity:
<input type="text" id="quantity" name="quantity" value="1">
</th>
</tr>
</thead>
<tbody>
<tr>
<td>
<input name="1_1" type="hidden" value="11" /><span>11</span>
</td>
<td>
<input name="1_2" type="hidden" value="12" /><span>12</span>
</td>
</tr>
<tr>
<td>
<input name="2_1" type="hidden" value="21" /><span>21</span>
</td>
<td>
<input name="2_2" type="hidden" value="22" /><span>22</span>
</td>
</tr>
<tr>
<td>
<input name="3_1" type="hidden" value="31" /><span>31</span>
</td>
<td>
<input name="2_2" type="hidden" value="32" /><span>32</span>
</td>
</tr>
</tbody>
</table>
LIVE DEMO
Happy Coding :)
It might be a bit over-kill for your needs, but this is what backbone.js aims to do - remove data from the HTML DOM and instead treats it Models and Views.
http://backbonejs.org/#examples
Apart from that, what's wrong with your current approach - what specifically do you want to improve?
The code cleaned up a bit:
$('#quantity').keyup(function() {
var quantity = parseFloat($(this).val());
quantity = ( quantity == "" || isNaN( quantity ) ? 1 : quantity;
$('#tbl tbody tr td').map(function() {
var $hiddenElement = $(this).find(input[type='hidden']);
$(this).html( '<input name="'+ $(hiddenElement).attr('name') +'" type="hidden" value="'+ $(hiddenElement).val() + '">' + (parseFloat($(hiddenElement).val()) * quantity) );
});
});
I think yours is just fine, the only thing I would personally do to improve it is place html in a var and use it as a template to keep syntax cleaner, I would replace this
$row.html( '<input name="'+ $refname +'" type="hidden" value="'+ $refvalue + '">' + $refvalue * quantity );
with this
var template ='<input name="{name}" type="hidden" value="{refvalue}">{res}</a>';
then
$row.html(template.replace('{name}', $refname) ); // and so on
Related
I have a PHP generated list of product links that, when clicked, adds a product to a shopping cart. At present, there's a quantity of '1' hard-coded in the links, e.g.
Add To Cart
I'd like to add a quantity field to each item in the list, so a customer can add the quantity they want to the cart.
This list doesn't use a form, so how could I introduce a user input qty field and use it in each link? My searches have turned up nothing, so I take it that it can't be done the way I have it set up now. No matter how I change this list, I need to pass an array to the /shop/checkout PHP script.
I'm probably looking at this the wrong way, so any pointers would be appreciated.
Thanks!
EDIT
It must have something to do with the fact that my product list is in a table. When I change your example to use a table instead of divs, it breaks. Here's a sample:
<table class="products_list">
<tr class="product_list--item">
<td> 12486XC4 </td>
<td> Amount: <span class="item_display--1[qty]">1</span> </td>
<td> <input class="item_qty" id="itm_qty" type="number" min="1" max="100" value="1" size="5" /> </td>
<td> Add to cart </td>
</tr>
<tr class="product_list--item">
<td> 13486XC5 </td>
<td> Amount: <span class="item_display--1[qty]">1</span> </td>
<td> <input class="item_qty" id="itm_qty" type="number" min="1" max="100" value="1" size="5" /> </td>
<td> Add to cart </td>
</tr>
<tr class="product_list--item">
<td> 14486XC6 </td>
<td> Amount: <span class="item_display--1[qty]">1</span> </td>
<td> <input class="item_qty" id="itm_qty" type="number" min="1" max="100" value="1" size="5" /> </td>
<td> Add to cart </td>
</tr>
</table>
Also, 1[sku] and 1[qty] are invariable in the links. They are used in the destination PHP script for each product on this page. The only thing that changes from product to product is the value of the sku.
You can use javascript for this instead of one big form and complex php code. Simply put each link in the wrapper with <input type="number"/> that will allow to add quantity to your product. Then you can change URI for checkout. Working example with comments of how to do this i have add below.
Hope that this will help!
Update
Because you are not showing your code its hard to understand what is not working on your side. So show us what you did and lets find out the issues instead of pin pointing the problem ;)
I don't see any issues with rendering your template using php and putting values of proper variables as a values of html attributes.
You can add name attribute which can be equal to your qty array name for proper sku. Example
<input name="1[qty]" class="item_qty" type=number min="1" max="100" value="1" />.
In php it will look like this (and again this is just an example of how you can achieve your result)
<input name="<?="1[qty]={$qty}";?>" class="item_qty" type=number min="<?=$qty;?>" max="100" value="1" />
<?=?> is an echo tag. You can replace with <?php ?>
Later you can simply grab the value of the attribute using JS and update each corresponding checkout link. Moreover your case didn't work because in RegExp symbols like [ and ] should be escaped -> \[ and \].
function addSlashes(string, vowels) {
let length = vowels.length;
let finalString = "";
let startOffset = 0;
let endOffset = 0;
for (let i = 0; i < length; i++) {
if ((endOffset = string.indexOf(vowels[i])) !== -1) {
finalString += string.substring(startOffset, endOffset) + "\\";
if (endOffset === string.length - 1) {
finalString += string[string.length - 1];
}
startOffset = endOffset;
}
}
return finalString;
}
function updateQueryStringParameter(uri, key, value) {
let escapedKey = addSlashes(key, ["[", "]"]);
let re = new RegExp("([?&])" + escapedKey + "=.*?(&|$)", "i");
let separator = uri.indexOf('?') !== -1 ? "&" : "?";
if (uri.match(re)) {
return uri.replace(re, '$1' + key + "=" + value + '$2');
} else {
return uri + separator + key + "=" + value;
}
}
function displayQuantityForProduct(element, text = "") {
element.textContent = text;
}
const inputs = document.querySelectorAll(".product_list--item .item_qty");
const length = inputs.length;
for (let i = 0; i < length; i++) {
inputs[i].addEventListener("input", function() {
// also add check whenever input value is not an empty string and its an integer which is bigger or equal to 1
if (this.value && parseInt(this.value) >= 1) {
// selfName
let selfName = "1[qty]";
let children = this.closest(".product_list--item").children;
// children will consist of td elements from each tr with class product_list--item in your table
// [0] first element of the array is sku (1) <td> 12486XC4 </td>
// [1] second element of the array is amount with span (2)
// [2] is input with qty (3)
// [3] is Add to cart link (4) and so on...
let displayQty = children[1].firstElementChild;
let addToCartLink = children[3].firstElementChild;
let newUri = updateQueryStringParameter(
addToCartLink.getAttribute("href"),
selfName,
this.value
);
displayQuantityForProduct(displayQty, this.value);
addToCartLink.setAttribute("href", newUri);
}
});
}
<table class="products_list">
<tr class="product_list--item">
<td> 12486XC4 </td>
<td> Amount: <span class="item_display--1[qty]">1</span> </td>
<td> <input class="item_qty" id="itm_qty" type="number" min="1" max="100" value="1" size="5" /> </td>
<td> Add to cart </td>
</tr>
<tr class="product_list--item">
<td> 13486XC5 </td>
<td> Amount: <span class="item_display--1[qty]">1</span> </td>
<td> <input class="item_qty" id="itm_qty" type="number" min="1" max="100" value="1" size="5" /> </td>
<td> Add to cart </td>
</tr>
<tr class="product_list--item">
<td> 14486XC6 </td>
<td> Amount: <span class="item_display--1[qty]">1</span> </td>
<td> <input class="item_qty" id="itm_qty" type="number" min="1" max="100" value="1" size="5" /> </td>
<td> Add to cart </td>
</tr>
</table>
I have to add values of inputs in each row in corresponding textbox (under the heading total) using jquery. I used jQuery as below. class 'value' used for inputs to be typed and class 'values' used for the values displayed (1st two colums).
jQuery code is given below:
jQuery(document).ready(function($) {
var $total = $('#total_mark_<?php echo $student['student_code'];?>'),
$value = $('.value');
$values = $('.values');
$value.on('input', function(e) {
var total = 0;
var t=0;
$value.each(function(index, elem) {
if(!Number.isNaN(parseFloat(this.value, 10)))
total = total + parseFloat(this.value, 10);
});
$values.each(function(index, elem) {
t = t + parseFloat(this.value, 10);
});
total=total+t;
$total.val(Math.round(total));
});
});
When I use this code, I am getting an output only in the last textbox(total-textbox in last row only), where all the values (all input fields)summed up and total is showing in a textbox only.
How to add values of inputs in each row in corresponding textbox using jQuery to show output in corresponding "total"textbox?
I created one demo here, from this demo you can check how to traverse throw DOM element and how to get values from it.
$( document ).ready(function() {
// Traverse throw all rows
$('.student_marks tbody tr').each(function(){
// Get current row
var student = $(this);
var total_points = 0;
$(student).find('.marks').each(function(){
total_points+=parseInt($(this).val());
})
$(student).find('.total').html(total_points);
})
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet"/>
<div class="container">
<table class="table student_marks" >
<thead>
<tr>
<th>Student Name</th>
<th>Math</th>
<th>History</th>
<th>Total</th>
</tr>
</thead>
<tbody>
<tr>
<td class="name">John</td>
<td><input value="50" readonly class="marks"/></td>
<td><input value="50" readonly class="marks"/></td>
<td class="total"></td>
</tr>
<tr>
<td class="name">Mac</td>
<td><input value="60" readonly class="marks"/></td>
<td><input value="50" readonly class="marks"/></td>
<td class="total"></td>
</tr>
<tr>
<td class="name">Sena</td>
<td><input value="40" readonly class="marks"/></td>
<td><input value="70" readonly class="marks"/></td>
<td class="total"></td>
</tr>
<tr>
<td class="name">Devy</td>
<td><input value="80" readonly class="marks"/></td>
<td><input value="90" readonly class="marks"/></td>
<td class="total"></td>
</tr>
</tbody>
</table>
</div>
Hard one to explain in the title, but a bit of code says it all:
<tr class="">
<td>
<input value="9" name="set[122][order]"></input>
<input class="set-id" type="hidden" value="1" name="set[122][ex_id]"></input>
</td>
<td>
<input value="0.00" name="set[122][weight]"></input>
</td>
<td> … </td>
<td>
<img class="deleteRowButton" border="0" title="Toggle Delete Set" alt="Delete Set" src="mysite/images/icons/png/delete-3x.png"></img>
</td>
</tr>
I have a bit of jQuery code that is activated when the img (deleteRowButton) is clicked:
$('.deleteRowButton').click (function() {
$(this).parents("tr").toggleClass( "deleteSet" );
var id = $('.set-id', $(this).closest('td')).val(); // this bit not working
$('.editWoForm').append('<input type="hidden" name="deleteSet[]" value="' + id + '" />');
});
The deleteRowButton code basically just inserts a hidden input tag at the bottom of my form, so i have the ability to process these to remove entries from db.
BUT, what I need to do is grab the value from set[], so in this example 122. It can come from any of the inputs, as the whole tr is related to one entry. 122 is the db id, so that's what I need to grab.
So ideally, when the user clicks on the deleteRowButton, it generates and inserts:
<input type="hidden" name="deleteSet[]" value="122" />
Thanks in advance!
Solution
Thanks to #ArunPJohny for the assistance.
$('.deleteRowButton').click (function() {
var $tr = $(this).parents("tr").toggleClass( "deleteSet" );
var id = $tr.find('.set-id').attr('name').match(/\d+/)[0];
if($tr.hasClass( "deleteSet" )){
$('.editWoForm').append('<input type="hidden" name="deleteSet[]" value="' + id + '" />');
}
else{
$('input[name="deleteSet[]"][value="' + id + '"]').remove();
}
});
This will get the id, append a hidden input field with said id as the value, then if the button is pressed again (to toggle the delete state) the hidden input field is removed.
One way here is to fine the set-id element which is within the current tr element. what you are trying to do is to find an set-id which is within the td which contains the clicked deleteRowButton.
$('.deleteRowButton').click(function() {
//use closest instead of parents
var $tr = $(this).closest("tr").toggleClass("deleteSet");
//find the set-id within the current tr
var id = $tr.find('.set-id').attr('name').match(/\d+/)[0];
//$('.editWoForm').append('<input type="hidden" name="deleteSet[]" value="' + id + '" />');
$('#log').text(id)
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<table>
<tr class="">
<td>
<input value="9" name="set[122][order]"/>
<input class="set-id" type="hidden" value="1" name="set[122][ex_id]"/>
</td>
<td>
<input value="0.00" name="set[122][weight]"/>
</td>
<td> … </td>
<td>
<img class="deleteRowButton" border="0" title="Toggle Delete Set" alt="Delete Set" src="mysite/images/icons/png/delete-3x.png"/>
</td>
</tr>
<tr class="">
<td>
<input value="9" name="set[123][order]"/>
<input class="set-id" type="hidden" value="2" name="set[123][ex_id]"/>
</td>
<td>
<input value="0.00" name="set[123][weight]"/>
</td>
<td> … </td>
<td>
<img class="deleteRowButton" border="0" title="Toggle Delete Set" alt="Delete Set" src="mysite/images/icons/png/delete-3x.png"/>
</td>
</tr>
</table>
<div id="log"></div>
This is my code
<table id="cont">
<tr>
<td><input type="text" name="no" id="no"/></td>
<td><input type="text" name="qty" id="qty"/></td>
</tr>
</table>
This is my jQuery Code
$(document).ready(function() {
var no="";
$('#no').keyup(function(){
no = $("#no").val();
for(var i=1; i<no; i++)
{
++j;
$('<tr class="field"><td></td><td><input name="qty[]" type="text" id="qty[0]" /></td></tr>').fadeIn('slow').appendTo('#cont');
}
});
if(i==1)
{
$('.field').remove();
}
});
I would like to create and remove row dynamically depending on an input field(no id) and it works fine upto 19 but if i input 20 then it create 20 with extra 1 row as well as i remove zero from 20 then it should be kept 2 rows but it display all rows(21).
How can i solve it , Please any help?
The main problem with your code is you only ever add rows. Here's a solution that provides a bit of timeout after keyup, then replaces all the rows. It's not entirely clear what your overall objective is with this UI.
Note that top row is wrapped in <thead> and <tbody> is used for data rows:
var row = '<tr class="field"><td>Row text</td><td><input name="qty[]" type="text" /></td></tr>';
var num_rows=0;
$('#no').keyup(function () {
num_rows= $(this).val();;
if (!isNaN(num_rows)) {/* make sure is a number, can add extra condition to limit number*/
setTimeout(createRows, 300);/* slight delay to give user time to type*/
} else {
alert('numbers only please')
}
});
function createRows(){
var rowHtml='';
for ( i=0;i<num_rows;i++){
rowHtml+=row;
}
$('#cont tbody').html( rowHtml)
}
Demo:http://jsfiddle.net/H4MHs/
EDIT: I suspect that this approach is completely off track from what you really want, but follows your methodology. Since objective was never spelled out that's all we can go on
You will probably want to convert the value from your field into an integer using parseInt before you use it in the loop.
I'm pretty sure jQuery's .val() will always return a string.
I have the feeling that this is what you need:
Html:
Number of field:<div id='nbElem'></div>
<table id="cont">
<tr>
<td><input type="text" name="no" id="no"/></td>
<td id='field'></td>
</tr>
</table>
Js:
$('#no').keyup(function(){
var $val = parseInt($(this).val(),10);
var $nbQtity = $('.qtity').length;
if($val <= $nbQtity){
for(var i = $val; i < $nbQtity; i++){
$('#q_'+i).remove();
}
}else{
for(var i = $nbQtity; i < $val; i++){
$('<input name="qty[]" class="qtity"'
+' type="text" id="q_'+i+'" />')
.fadeIn('slow')
.appendTo('#field');
}
}
$('#nbElem').text($val);
});
http://jsfiddle.net/pYtbs/
This is the simplest and the easiest way of adding rows
<table id="options-table">
<tbody>
<tr>
<td>Input-Box-One</td>
<td>Input-Box-Two</td>
<td></td>
</tr>
<tr>
<td><input type="text" name="input_box_one[]" /></td>
<td><input type="text" name="input_box_one[]" /></td>
<td><input class="del" type="button" value="Delete" /></td>
</tr>
<tr>
<td><input type="text" name="input_box_one[]" /></td>
<td><input type="text" name="input_box_one[]" /></td>
<td><input class="add" type="button" value="Add More" /></td>
</tr>
</tbody>
If we want more rows then we have to add new row to the table.
Put this code in script
$('.add').live('click',function(){
$(this).val('Delete');
$(this).attr('class','del');
var appendTxt = "<tr><td><input type="text" name="input_box_one[]" /></td><td><input type="text" name="input_box_two[]" /></td><td><input class="add" type="button" value="Add More" /></td></tr>";
$("tr:last").after(appendTxt); });
Delete a row from Table.
$('.del').live('click',function(){
$(this).parent().parent().remove(); });
I wanted to put a checkbox autosum on my website so that anyone who check a box and submit, the values (Points) of those check box are automatically added to my total sum (on home page actually)
I have found this code so far for java script.
<table border="0" cellpadding="0" cellspacing="0" width="100%">
<tr>
<td> <input name="sum_m_1" value="25" type="checkbox" id="sum_m_1" onclick="UpdateCost()"> </td>
<td> ResponseOption_1 </td>
</tr>
<tr>
<td> <input name="sum_m_2" value="15" type="checkbox" id="sum_m_2" onclick="UpdateCost()"> </td>
<td> ResponseOption_2 </td>
</tr>
</table>
<input type="text" id="totalcost" value="">
With JAVASCRIPT:
<script type="text/javascript">
function UpdateCost() {
var sum = 0;
var gn, elem;
for (i=1; i<3; i++) {
gn = 'sum_m_'+i;
elem = document.getElementById(gn);
if (elem.checked == true) { sum += Number(elem.value); }
}
document.getElementById('totalcost' ).value = sum.toFixed(2);
}
window.onload=UpdateCost
</script>
This will add up the values but i wanted to add by checking check boxes --> Submit --> collect the data --> add to my main total.
Any helps would be much appreciated.
Simple changes:
Add a button "calculate cost".
Removed the onclick events from the checkboxes and added the onclick event to the button instead.
Note that "window.onload=UpdateCost" is still there because what you want ideally is for the total cost to be displayed properly as 0.00 when the page loads.
HTML
<table border="0" cellpadding="0" cellspacing="0" width="100%">
<tr>
<td> <input name="sum_m_1" value="25" type="checkbox" id="sum_m_1"> </td>
<td> ResponseOption_1 </td>
</tr>
<tr>
<td> <input name="sum_m_2" value="15" type="checkbox" id="sum_m_2"> </td>
<td> ResponseOption_2 </td>
</tr>
</table>
<input type="text" id="totalcost" value="">
<input type="button" value="update cost" onclick="UpdateCost();">
JavaScript
<script type="text/javascript">
function UpdateCost() {
var sum = 0;
var gn, elem;
for (i=1; i<3; i++) {
gn = 'sum_m_'+i;
elem = document.getElementById(gn);
if (elem. checked == true) { sum += Number(elem. value); }
}
document.getElementById('totalcost' ).value = sum.toFixed(2);
}
window.onload=UpdateCost
</script>
Hope that's the kind of thing you wanted, let me me know what you think.