jquery/javascript: add to array in case tr has certain class - javascript

I have a dynamic html table:
<table>
<tbody>
<tr>
<td>Name</td>
<td>City</td>
</tr>
<tr class="new" id="item1">
<td><input class="names" value="John Smith" type="hidden">John Smith</td>
<td><input class="cities" value="London" type="hidden">London</td>
</tr>
<tr class="normal" id="item2">
<td><input class="names" value="Regina Mills" type="hidden">Regina Mills</td>
<td><input class="cities" value="Berlin" type="hidden">Berlin</td>
</tr>
<tr class="normal" id="item3">
<td><input class="names" value="Marcus Bell" type="hidden">Marcus Bell</td>
<td><input class="cities" value="Liverpool" type="hidden">Liverpool</td>
</tr>
</tr>
</tbody>
</table>
From my js file I'm storing the information in this way:
var arrayNames = [];
$(".names").each(function(){
arrayNames.push($(this).val());
})
var arrayCities = [];
$(".cities").each(function(){
arrayCities.push($(this).val());
})
params += '&names='+arrayNames;
params += '&cities='+arrayCities;
With this I am getting in my php:
$_REQUEST['names']
: string = John Smith,Regina Mills,Marcus Bell
$_REQUEST['cities']
: string = London,Berlin,Liverpool
But I only need in the $_REQUESTs the values when the class in the table tr's is "new"
How can I do that?
Thanks!

You could try
$(".names").each(function(){
if ($( this ).parent().attr( "class" ) == "new")
arrayNames.push($(this).val());
})

Just target the .names within .new. You can use map() to get the values:
var arrayNames = $('.new .names').map(function() { return this.value; }).get();
.. and do the same thing for .cities

Related

How to insert multiple element into an array in JQuery?

I make a table in a form to enable user to submit several item in one time. I am able to use jquery to get the first row of the value input by user. But when they type in the value in the second row, it show error. I am pretty sure there is something wrong with the array that I am using. I have try 2 methods, both method work but it only takes the value from first row only.
<form>
<table>
<thead>
<tr>
<th>Item Code</th>
<th>Item Name</th>
<th>Status</th>
</tr>
</thead>
<tbody id="entrybody">
<tr>
<td><input type="text" name="prd_code"></td>
<td><input type="text" name="prd_name"></td>
<td><input type="text" name="prd_cond"></td>
</tr>
<tr>
<td><input type="text" name="prd_code"></td>
<td><input type="text" name="prd_name"></td>
<td><input type="text" name="prd_cond"></td>
</tr>
<tr>
<td><input type="text" name="prd_code"></td>
<td><input type="text" name="prd_name"></td>
<td><input type="text" name="prd_cond"></td>
</tr>
</tbody>
</table>
</form>
$(function() {
$.post("action.php", function(data) {
$("[name='title']").val(data.title);
$("[name='body']").val(data.body);
}, "json");
setInterval(function() {
var itemlist = new Array;
var count = 1;
var title = $("[name='title']").val();
var body = $("[name='body']").val();
itemlist[count - 1] = {};
$("#productbody tbody tr").each(function() {
var that = $(this);
if (that.find("[name='prd_code']").val().length !== 0) {
/*itemlist.push(code);
itemlist.push(name);
itemlist.push(cond);*/ //method 1
itemlist[count - 1].code = that.find("[name='prd_code']").val();
itemlist[count - 1].name = that.find("[name='prd_name']").val();
itemlist[count - 1].cond = that.find("[name='prd_cond']").val(); //method 2
count++;
}
});
console.log(itemlist);
}, 2000);
});
===== Console message (first row) =====
0:
code: "test_code1"
cond: "test_status1"
name: "test_name1"
I've changed the method of the event to a .change() for this example.
Then I've changed the following code:
var itemlist = new Array;
var title = $("[name='title']").val();
var body = $("[name='body']").val();
$("#productbody tbody tr").each(function(i) {
var that = $(this);
if (that.find("[name='prd_code']").val().length !== 0) {
itemlist[i] = {};
itemlist[i].code = that.find("[name='prd_code']").val();
itemlist[i].name = that.find("[name='prd_name']").val();
itemlist[i].cond = that.find("[name='prd_cond']").val(); //method 2
}
});
One problem was that you use this itemlist[count - 1] = {}; before your foreach statement. so you only created the first object.
Demo
$(function() {
$("#productbody tbody tr input").change(function() {
//setInterval(function() {
var itemlist = new Array;
var title = $("[name='title']").val();
var body = $("[name='body']").val();
$("#productbody tbody tr").each(function(i) {
var that = $(this);
if (that.find("[name='prd_code']").val().length !== 0) {
itemlist[i] = {};
itemlist[i].code = that.find("[name='prd_code']").val();
itemlist[i].name = that.find("[name='prd_name']").val();
itemlist[i].cond = that.find("[name='prd_cond']").val(); //method 2
}
});
console.log(itemlist);
});
//}, 2000);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<form>
<table id="productbody">
<thead>
<tr>
<th>Item Code</th>
<th>Item Name</th>
<th>Status</th>
</tr>
</thead>
<tbody id="entrybody">
<tr>
<td><input type="text" name="prd_code"></td>
<td><input type="text" name="prd_name"></td>
<td><input type="text" name="prd_cond"></td>
</tr>
<tr>
<td><input type="text" name="prd_code"></td>
<td><input type="text" name="prd_name"></td>
<td><input type="text" name="prd_cond"></td>
</tr>
<tr>
<td><input type="text" name="prd_code"></td>
<td><input type="text" name="prd_name"></td>
<td><input type="text" name="prd_cond"></td>
</tr>
</tbody>
</table>
</form>
As far as I understand you want to create an array of the values from all table cells in all rows. Here is a relative simple way to do this without JQuery.
document.addEventListener(`change`, handle);
function handle(evt) {
if (evt.target.name.startsWith(`prd_`)) {
// retrieve all rows
const values = [...document.querySelectorAll(`tbody tr`)]
// map to objects containing row number and values
.map(row => ({
row: row.rowIndex,
values: [...row.querySelectorAll(`[name^='prd_']`)]
.reduce( (acc, val) => ({...acc, [val.name]: val.value}), {})
}))
.filter(val => (val.values.prd_code || ``).trim().length > 0);
document.querySelector(`pre`).textContent = JSON.stringify(values, null, 2);
}
}
<table>
<thead>
<tr>
<th>Item Code</th>
<th>Item Name</th>
<th>Status</th>
</tr>
</thead>
<tbody>
<tr>
<td><input type="text" name="prd_code"></td>
<td><input type="text" name="prd_name"></td>
<td><input type="text" name="prd_cond"></td>
</tr>
<tr>
<td><input type="text" name="prd_code"></td>
<td><input type="text" name="prd_name"></td>
<td><input type="text" name="prd_cond"></td>
</tr>
<tr>
<td><input type="text" name="prd_code"></td>
<td><input type="text" name="prd_name"></td>
<td><input type="text" name="prd_cond"></td>
</tr>
</tbody>
</table>
<pre></pre>

How to get all values inside HTML table using JQuery

I have a table which looks like below and i want to get all values inside the table including the value of text box and check box.
<div class="container-fluid">
<h1 class="h3 mb-4 text-gray-800"><?= $title; ?></h1>
<div class="container" style="text-align: left">
<table class="table table-sm" id="tbl">
<thead>
<tr>
<th>No</th>
<th>Checklist Item</th>
<th>Cheklist</th>
<th>Actual</th>
<th>Recomended</th>
</tr>
</thead>
<tbody>
<tr>
<td scope="row">1</td>
<td>Check and clean rubber roller cage</td>
<td><input type="checkbox" name="chek" id="check"></td>
<td><input type="text"></td>
<td><input type="text"></td>
</tr>
<tr>
<td scope="row">2</td>
<td>Tension Rod all </td>
<td><input type="checkbox" name="chek" id="check"></td>
<td><input type="text"></td>
<td><input type="text"></td>
</tr>
<tr>
<td scope="row">3</td>
<td>Delete all unnecessary file from system</td>
<td><input type="checkbox" name="chek" id="check"></td>
<td><input type="text"></td>
<td><input type="text"></td>
</tr>
</table>
save
</div>
when i grab all value using this script i cant get value inside the text box and checkbox
$(document).on('click', '#save', function() {
var myRows = [];
var headersText = [];
var $headers = $("th");
// Loop through grabbing everything
var $rows = $("tbody tr").each(function(index) {
$cells = $(this).find("td");
myRows[index] = {};
$cells.each(function(cellIndex) {
// Set the header text
if (headersText[cellIndex] === undefined) {
headersText[cellIndex] = $($headers[cellIndex]).text();
}
// Update the row object with the header/cell combo
myRows[index][headersText[cellIndex]] = $(this).text();
});
});
var myObj = {
"Array": myRows
};
alert(JSON.stringify(myObj));
});
I want to convert it to JSON but the value of text box and check box not shows inside table. Kindly help me to resolve this issue.
Thank you in advance.
You can find the input and use .val() to get its value if the table cell's text is empty. Checkboxes and text inputs will need to be handled separately.
const text = $(this).text();
if(text){
myRows[index][headersText[cellIndex]] = text;
} else {
const input = $(this).find('input');
if(input.is(":checkbox")){
myRows[index][headersText[cellIndex]] = +input.prop('checked');
} else {
myRows[index][headersText[cellIndex]] = input.val();
}
}

how to get the remaining qty per item using javascript

I have a problem here that when I click copy row and I want to get the remaining qty per item, the result is not accurate.
So let's just say the item mouse has 100 qty, and I inputted new qty for 50. So the remaining should be 50. And when I copied the item mouse and inputted 40, so the remaining now is 10. Same goes for other items. This should be the expected output.
Current Situation
JSFIDDLE
$('.qty').on("keyup", function() {
var id = $(this).data('id');
var value = $(this).val();
var sum = 0;
$("#table_name .qty").filter(function(){
if ($(this).data("id") == id){
sum += parseFloat(value);
}
});
console.log(sum);
$('.remaining').val(sum);
});
Your overall logic is REALLY unclear. Here is an example that might help.
$(function() {
function refreshIndex($t) {
$('tbody tr', $t).each(function(i, el) {
var c = i + 1;
var select = $(this).find('td:eq(0)').text(c);
});
}
function copyRow(e) {
var self = $(e.target);
var row = self.closest("tr");
row.clone().appendTo(self.closest("tbody"));
refreshIndex($("#table_name"));
}
function updateItem(e) {
var self = $(e.target);
var row = self.closest("tr");
var p = parseInt(self.val());
var q = parseInt(row.find("td:eq(2) input").val());
$('.remaining', row).val(q - p);
}
$("#table_name tbody").on("keyup", '.price', updateItem);
$("#table_name tbody").on('click', '.copy', copyRow);
});
#table_name tr td input {
width: 4em;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table id="table_name">
<thead>
<tr>
<th>No</th>
<th>Item</th>
<th>Total</th>
<th>Qnty</th>
<th>Action</th>
<th>Remaing</th>
</tr>
</thead>
<tbody>
<tr class="trs" id="tr-1">
<td>1</td>
<td>Mouse</td>
<td><input type="text" value="100" readonly></td>
<td><input type="text" class="price" data-id="79"></td>
<td><button class="copy" id="copy-1">Copy</button></td>
<td><input type="text" class="remaining"></td>
</tr>
<tr class="trs" id="tr-2">
<td>2</td>
<td>Keyboard</td>
<td><input type="text" value="20" readonly></td>
<td><input type="text" class="price" data-id="80"></td>
<td><button class="copy" id="copy-2">Copy</button></td>
<td><input type="text" class="remaining"></td>
</tr>
<tr class="trs" id="tr-3">
<td>3</td>
<td>Monitor</td>
<td><input type="text" value="50" readonly></td>
<td><input type="text" class="price" data-id="81"></td>
<td><button class="copy" id="copy-3">Copy</button></td>
<td><input type="text" class="remaining"></td>
</tr>
</tbody>
</table>
When I enter 40 under Price, 60 appears as the difference between the Quantity and the Amount entered.
When Copy is clicked, a new row is appended, and functionality is binded to it already due to use of .on().
Hope that helps.
Basically you can use the data-id attribute to target the rows you actually want to update.
var clone_controll = function(num) {
//Needed to mod this so add rows have the event handler
$('#table_name').on("keyup", ".qty", function() {
var id = $(this).data('id');
var value = $(this).val();
var sum = 0;
//Filter is the wrong choice here - it is designed to filter objects
/*$("#table_name .qty").filter(function(){
if ($(this).data("id") == id){
//I think this logic is incorrect as well
//You are only getting the value from the
//field you are typing in
sum += parseFloat(value);
}
});*/
/*Use a better selector with each()*/
$("#table_name [data-id=" + id +"]").each(function(){
//In this context "this" is the item iterated in "each"
sum += parseFloat($(this).val());
console.log(sum);
});
console.log("Final: " + sum);
//Here is your problem, this updates All "remaining fields
//$('.remaining').val(sum);
//All rows contiaining this data id
var relevantRows = $("[data-id=" + id + "]").closest("tr");
//Update the "remaining fields in those rows
$(relevantRows).find(".remaining").val(sum);
});
}
clone_controll();
var $tableBody = $('#table_name').find("tbody");
clickEvent();
function clickEvent(){
$tableBody.find('.copy').off('click').on('click',function() {
$trLast = $(this).closest('tr'),
$trNew = $trLast.clone();
$trLast.after($trNew);
clickEvent();
clone_controll();
});
function refresh_index(){
$('#table_name > tbody > tr').each(function (i) {
i++;
var select = $(this).find('td').eq(0).text(i);
});
}
refresh_index();
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.0/jquery.min.js"></script>
<table id="table_name">
<thead>
<tr>
<th>No</th>
<th>Item</th>
<th>Qty</th>
<th>Your Qty</th>
<th>Action</th>
<th>Remaing per item(not per row)</th>
</tr>
</thead>
<tbody>
<tr class="trs" id="tr-1">
<td>1</td>
<td>Mouse</td>
<td><input type="text" value="100" readonly></td>
<td><input type="text" class="qty" data-id="79"></td>
<td><button class="copy" id="copy-1">Copy</button></td>
<td><input type="text" class="remaining"></td>
</tr>
<tr class="trs" id="tr-2">
<td>2</td>
<td>Keyboard</td>
<td><input type="text" value="20" readonly></td>
<td><input type="text" class="qty" data-id="80"></td>
<td><button class="copy" id="copy-2">Copy</button></td>
<td><input type="text" class="remaining"></td>
</tr>
<tr class="trs" id="tr-3">
<td>3</td>
<td>Monitor</td>
<td><input type="text" value="50" readonly></td>
<td><input type="text" class="qty" data-id="81"></td>
<td><button class="copy" id="copy-3">Copy</button></td>
<td><input type="text" class="remaining"></td>
</tr>
</tbody>
</table>
Your logic is still pretty unclear, but hopefully this gets you moving in the right direction.

Angular checkbox filter leaves no data

My checkbox filter is totally removing all data records instead of filtering.
I used this post as guidance: http://jsfiddle.net/65Pyj/
I can get and console the selected category. I am having problems filtering the list.
My data is like so:
{"product_title":"COPD Track Package","product_code":"COPDPKG2014","id":"a1u40000000C182AAC","Id":"a1u40000000C182AAC","sort_order":"6","sort_code":"COPDPKG2014","category":["Postgraduate Course, Continuing Education"]}
Here is the angular:
<div class="container">
<div class="ng-scope" ng-app="products">
<div class="ng-scope" ng-controller="ShoppingCartCtrl">
<div class="row">
<div class="col-sm-7"><h3 class="colored-title">Search Filter</h3>
<table class="table table-striped table-bordered">
<tbody>
<tr>
<td>By Product Title:</td>
<td><input ng-model="search.product_title" type="text"/></td>
</tr>
<tr>
<td>By Product Code:</td>
<td><input ng-model="search.product_code" type="text"/></td>
</tr>
<tr>
<td>By Presentation Title:</td>
<td><input ng-model="search.presentations" type="text"/></td>
</tr>
<tr>
<td>By Speaker Name:</td>
<td><input ng-model="search.speakers" type="text"/></td>
</tr>
<tr>
<td><input type="checkbox" ng-click="includeProduct('Postgraduate Course')"/>Postgraduate Course</td>
<td><input type="checkbox" ng-click="includeProduct('Continuing Education')"/>Continuing Education</td>
</tr>
<tr><td>Filter dump: {{productIncludes}}</td></tr>
</tbody>
</table></div>
</div>
<div>Sort by:<select ng-model="sortExpression">
<option value="sort_code">Product Code</option>
<option value="product_title">Product Title</option>
</select></div>
<table class="table table-bordered table-striped">
<thead>
<tr class="warning"><th>Product Code</th><th>Product Title</th></tr>
</thead>
<tbody>
<tr ng-repeat="item in items | orderBy:mySortFunction | filter:search |filter:productFilter">
<td valign="top">
{{item.id}}<div ng-repeat="c in item.cat" >{{c}}</div>
</td>
<td>
{{item.product_title}}
</tr>
</tbody>
</table>
</div>
$scope.productIncludes = [];
$scope.includeProduct = function(category){
var i = $.inArray(category, $scope.productIncludes);
if(i > -1){
$scope.productIncludes.splice(i,1);
}else{
$scope.productIncludes.push(category);
}
console.log($scope.items.length);
}
$scope.productFilter = function (items) {
if ($scope.productIncludes.length > 0) {
if ($.inArray(items.cat, $scope.productIncludes) < 0) return;
}
return items;
}
Basically it is problem with your data representations.
You have categories stored as "category":["Postgraduate Course, Continuing Education"] and you want to search in those categories as if it was an array like "category":["Postgraduate Course", "Continuing Education"].
I recommend you to represent your data like the second case and then you can iterate over it like this:
$scope.productFilter = function (items) {
if ($scope.productIncludes.length > 0) {
var result = $scope.productIncludes.filter(function(n) {
return items.category.indexOf(n) != -1
});
if(result.length < 1) {
return;
}
}
return items;
}
And here is your fiddle: http://jsfiddle.net/65Pyj/133/
Short explanation:
filter function in combination with the indexOf function will return an intersection of the two arrays.

Change the value of a text box to its current order in a sortable tab

Edit: I have solved this by myself. See my answer below
I have set up a nice sortable table with jQuery and it is quite nice. But now i want to extend it.
Each table row has a text box, and i want i am after is to, every time a row is dropped, the text boxes update to reflect the order of the text boxes. E.g. The text box up the top always has the value of '1', the second is always '2' and so on.
I am using jQuery and the Table Drag and Drop JQuery plugin
Code
Javascript:
<script type = "text/javascript" >
$(document).ready(function () {
$("#table-2").tableDnD({
onDrop: function (table, row) {
var rows = table.tBodies[0].rows;
var debugStr = "Order: ";
for (var i = 0; i < rows.length; i++) {
debugStr += rows[i].id + ", ";
}
console.log(debugStr)
document.forms['productform'].sort1.value = debugStr;
document.forms['productform'].sort2.value = debugStr;
document.forms['productform'].sort3.value = debugStr;
document.forms['productform'].sort4.value = debugStr;
},
});
});
</script>
HTML Table:
<form name="productform">
<table cellspacing="0" id="table-2" name="productform">
<thead>
<tr>
<td>Product</td>
<td>Order</td>
</tr>
</thead>
<tbody>
<tr class="row1" id="Pol">
<td>Pol</td>
<td><input type="textbox" name="sort1"/></td>
</tr>
<tr class="row2" id="Evo">
<td>Evo</td>
<td><input type="textbox" name="sort2"/></td>
</tr>
<tr class="row3" id="Kal">
<td>Kal</td>
<td><input type="textbox" name="sort3"/></td>
</tr>
<tr class="row4" id="Lok">
<td>Lok</td>
<td><input type="textbox" name="sort4"/></td>
</tr>
</tbody>
</table>
</form>
Hardnrg in #jquery ended up solving it for me.
It involved adding an id="" to each input:
<form name="productform">
<table cellspacing="0" id="table-2" name="productform">
<thead>
<tr><td>Product</td> <td>Order</td></tr>
</thead>
<tbody>
<tr class="row1" id="Pol"> <td>Pol</td> <td><input id="Pol_field" type="textbox" name="sort1"/></td> </tr>
<tr class="row2" id="Evo"> <td>Evo</td> <td><input id="Evo_field" type="textbox" name="sort2"/></td> </tr>
<tr class="row3" id="Kal"> <td>Kal</td> <td><input id="Kal_field" type="textbox" name="sort3"/></td> </tr>
<tr class="row4" id="Lok"> <td>Lok</td> <td><input id="Lok_field" type="textbox" name="sort4"/></td> </tr>
</tbody>
</table>
</form>
And add this js to the OnDrop event:
for (var i=0; i < rows.length; i++) {
$('#' + rows[i].id + "_field").val(i+1);
}
Easy peasy!
Hmmm..
I think you want to do something like this:
$("input:text", "#table-2").each( function(i){ this.value=i+1; });
The $().each() function's info is here: http://docs.jquery.com/Core/each

Categories