How to concatenate strings from separate elements with jquery / javascript - javascript

I am wanting to concatenate strings from 2 separate elements and have them stored in a variable.
Currently my code is setting the variable equal to:
"Daily: 1070300, Weekly: 1070300, Monthly: 1070300"
My goal is to make the variable in the console equal to:
"Daily: 10, Weekly: 70, Monthly: 300"
$(document).ready(function() {
var str = '';
$('tbody > tr').each(function() {
$(this).find('.key').each(function() {
str += $(this).text() + ": " + $(this).parents().siblings('tr').find('.value').text() + ", ";
})
});
console.log(str);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table>
<tbody>
<tr>
<th class="key">Daily</th>
<th class="key">Weekly</th>
<th class="key">Monthly</th>
</tr>
<tr>
<td class="value">10</td>
<td class="value">70</td>
<td class="value">300</td>
</tr>
</tbody>
</table>
Thank you for your help all!

Each time through the key loop, you're grabbing the content of all three value cells (since $(this).parents().siblings('tr').find('.value') matches all three). There are many ways to fix this but one easy one I see is to use the index argument on the inner loop to select the value cell corresponding to the current key (using jQuery's eq function):
$(document).ready(function() {
var str = '';
$('tbody > tr').each(function() {
$(this).find('.key').each(function(index) {
str += $(this).text() + ": " + $(this).parents().siblings('tr').find('.value').eq(index).text() + ", ";
})
});
console.log(str);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table>
<tbody>
<tr>
<th class="key">Daily</th>
<th class="key">Weekly</th>
<th class="key">Monthly</th>
</tr>
<tr>
<td class="value">10</td>
<td class="value">70</td>
<td class="value">300</td>
</tr>
</tbody>
</table>

The code is very inefficient when you keep looking up stuff in the loop. So fixing it to read the index would work, it just causes the code to do more work than needed.
How can it be improved. Look up the two rows and one loop using the indexes.
var keys = $("table .key") //select the keys
var values = $("table .value") //select the values
var items = [] // place to store the pairs
keys.each(function(index, elem){ //loop over the keys
items.push(elem.textContent + " : " + values[index].textContent) // read the text and use the index to get the value
})
console.log(items.join(", ")) // build your final string by joing the array together
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table>
<tbody>
<tr>
<th class="key">Daily</th>
<th class="key">Weekly</th>
<th class="key">Monthly</th>
</tr>
<tr>
<td class="value">10</td>
<td class="value">70</td>
<td class="value">300</td>
</tr>
</tbody>
</table>

Collect the .key and .value classes into a NodeList convert the NodeList into arrays. Then merge the 2 arrays into key/value pairs stored in an Object Literal. Finally convert the object into a string so it can be displayed.
Demo
Details are commented in Demo
// Collect all th.key into a NodeList and turn it into an array
var keys = Array.from(document.querySelectorAll('.key'));
// As above with all td.value
var vals = Array.from(document.querySelectorAll('.value'));
function kvMerge(arr1, arr2) {
// Declare empty arrays and an object literal
var K = [];
var V = [];
var entries = {};
/* map the first array...
|| Extract text out of the arrays
|| Push text into a new array
|| Then assign each of the key/value pairs to the object
*/
arr1.map(function(n1, idx) {
var txt1 = n1.textContent;
var txt2 = arr2[idx].textContent;
K.push(txt1);
V.push(txt2);
entries[K[idx]] = V[idx];
});
return entries;
}
var result = kvMerge(keys, vals);
console.log(result);
// Reference the display area
var view = document.querySelector('.display');
// Change entries object into a string
var text = JSON.stringify(result);
// Clean up the text
var final = text.replace(/[{"}]{1,}/g, ``);
// Display the text
view.textContent = final
<table>
<tbody>
<tr>
<th class="key">Daily</th>
<th class="key">Weekly</th>
<th class="key">Monthly</th>
</tr>
<tr>
<td class="value">10</td>
<td class="value">70</td>
<td class="value">300</td>
</tr>
</tbody>
<tfoot>
<tr>
<td class='display' colspan='3'></td>
</tr>
</tfoot>
</table>

You can also solve that using unique ids, like that:
$(document).ready(function() {
var str = '';
$('tbody > tr').each(function() {
$(this).find('.key').each(function() {
var index = $(this).attr('id').slice(3)
str += $(this).text() + ": " + $('#value'+index).text() + ", ";
})
});
console.log(str);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table>
<tbody>
<tr>
<th class="key" id="key1">Daily</th>
<th class="key" id="key2">Weekly</th>
<th class="key" id="key3">Monthly</th>
</tr>
<tr>
<td class="value" id="value1">10</td>
<td class="value" id="value2">70</td>
<td class="value" id="value3">300</td>
</tr>
</tbody>
</table>

Related

I'd like to create a JSON object out of an HTML table. I'd like the end product to be used to tally input from multiple users

Active learner here, trying to figure out how to create a JSON object out of HTML table. I only want the value of one specific TD and want to give each value an incrementing number as a key. I'd like an output like below. My table has a TD for the city names, but it does not have one with a incrementing numerical value so I'd need to add that another way.
{
"mycities" : [
{
"Seattle" : "1",
"Chicago" : "2",
"New York" : "3"
"Pitt" : "4",
"LA" : "5",
"Fresno" : "6"
},
]
}
Here is what my table looks like:
<table>
<thead>
<tr>
<th>city name</th>
<th>other city info</th>
</tr>
</thead>
<tbody>
<tr>
<td>Seattle</td>
<td>Lots of rain</td>
</tr>
etc,etc,etc
</tbody>
</table>
I've tried using a replacer function but haven't got it figured out after much googling. Any help is appreciated!
$(document).ready(function(){
$("body").on("click",".submitButtonPri",function(){
count= 1;
function replacer(key, value) {
if (typeof value === 'string') {
return count;
}
return value;
}
var myRows = [];
var $headers = $(".rightDash > table thead th");
var $rows = $(".rightDash > table tbody tr").each(function(index) {
$cells = $(this).find("td.titlePri");
myRows[index] = {};
$cells.each(function(cellIndex) {
myRows[index][$($cells[cellIndex]).text()] = $(this).text();
});
count++;
});
var myObj = {};
myObj.myrows = myRows;
console.log(JSON.stringify(myObj,replacer));
});
});
Use reduce to iterate over the trs in the body, using the text content of the first td in the tr as the city name. The third argument to the function provided to reduce represents the iteration index:
const cityData = [...document.querySelectorAll('tbody > tr')]
.reduce((a, tr, i) => {
a[tr.children[0].textContent] = i + 1;
return a;
}, {});
console.log(
{ mycities: [
cityData
]}
);
<table>
<thead>
<tr>
<th>city name</th>
<th>other city info</th>
</tr>
</thead>
<tbody>
<tr>
<td>Seattle</td>
<td>Lots of rain</td>
</tr>
<tr>
<td>Chicago</td>
<td>Lots of rain</td>
</tr>
<tr>
<td>New York</td>
<td>Lots of rain</td>
</tr>
</tbody>
</table>
You can start with this simple script:
$('td').each(function(index, obj) {console.log(index, $(this).html())});
It returns all what you need and you just need assemble JSON by any way

Onclick in td - access next cells

I'm using a table to display items, an onclick event on cell[0] should output (alert) the data from cell[1] and cell[2].
I'm not sure with which approach I could access them.
Here is my code so far
http://jsfiddle.net/5uua7eyx/3/
Perhaps there is a way to use my variable input
HTML
<table id="items">
<tr>
<td onclick="ClickPic(this)">Picture0</td>
<td>Name0</td>
<td>Price0</td>
</tr>
<tr>
<td onclick="ClickPic(this)">Picture1</td>
<td>Name1</td>
<td>Price1</td>
</tr>
</table>
JS
function ClickPic(e) {
"use strict";
var input = e.target;
alert("Clicked!");
}
Thank you
You're passing this, which represents the element clicked, not the event object.
All you need to do is use the parameter to get the sibling .cells from the .parentNode, then use the elem.cellIndex to figure out the next indices:
function ClickPic(elem) {
"use strict";
var cells = elem.parentNode.cells;
var currIdx = elem.cellIndex;
alert(cells[currIdx + 1].textContent + " " + cells[currIdx + 2].textContent);
}
<table id="items">
<tr>
<td onclick="ClickPic(this)">Picture0</td>
<td>Name0</td>
<td>Price0</td>
</tr>
<tr>
<td onclick="ClickPic(this)">Picture1</td>
<td>Name1</td>
<td>Price1</td>
</tr>
</table>
x
If you know the index numbers will always be 1 and 2, then you can shorten it.
alert(cells[1].textContent + " " + cells[2].textContent);
you can change your js function to something like this
<script type="text/javascript">
function ClickPic(e) {
var s = '';
$(e).siblings().each(function() {
s = s + ',' + $(this).text()
});
alert(s);
}

Length of data() parameter in first TR of a table is "undefined" at click but not at further TRs

I am having a table
<table width="100%" border="0" cellpadding="2" cellspacing="0" class="msctrans_navtree">
<tr class="msctrans_navrow" data-subs="603" data-navlevel="1" data-sp_id="2" data-standardsprache="1">
<td><strong>Test</strong></td>
</tr>
<tr>
<td bgcolor="#ffffff" colspan="2">List of documents</td>
</tr>
<tr class="msctrans_navrow" data-subs="" data-navlevel="1" data-sp_id="2" data-standardsprache="1">
<td><strong>Test 1</strong></td>
</tr>
<tr>
<td bgcolor="#ffffff" colspan="2">List of documents 1</td>
</tr>
<tr class="msctrans_navrow" data-subs="334,23,5,21" data-navlevel="1" data-sp_id="2" data-standardsprache="1">
<td><strong>Test 2</strong></td>
</tr>
<tr>
<td bgcolor="#ffffff" colspan="2">List of documents 2</td>
</tr>
Clicking on the TR with class "msctrans_navrow" should do something regarding the data parameters of the clicked element:
$(".msctrans_navrow").click(function() {
var clicked = $(this);
var subs = clicked.data("subs");
var navlevel = clicked.data("navlevel");
var sp_id = clicked.data("sp_id");
var spstandard = clicked.data("standardsprache");
alert(subs + " = " + subs.length);
// Action only if there are subs
if (subs.length) {
clicked.toggleClass("mscajaxloaderdivabsolut");
var insertAfter = clicked.next();
alert("Now I am doing some Ajax and inert it after the inserAfter element.");
}
});
Unfortunately when clicking the first TR where the data-subs parameters value is 603 subs.length in the script delivers an "undefined". I can't figure why that is.
Here is a fiddle to play around with it: http://jsfiddle.net/9B9AW/9/
It's because it's stored as a number, not a string, inside jQuery's data cache for that element. Numbers don't have a length property. You could force a conversion to string by calling .toString():
if(subs.toString().length) {
// code if the string representation of `subs` has a length > 0
}
Alternatively you could use the .attr() method instead, which won't convert (always retrieves the value as a string):
var subs = clicked.attr("data-subs");
Change var subs = clicked.data("subs");
to var subs = ""+clicked.data("subs"); // make it a String
Demo ---> http://jsfiddle.net/9B9AW/10/

create json object from html table using selected colums using jquery

i was wondering how to parse html table to get json object that i can send via $.post with jquery.
i have a table
<table id="Report">
<thead>
<tr>
<th>Kod</th>
<th>Nazwa</th>
<th>Ilość</th>
<th>Netto / 1szt.</th>
<th>Suma brutto</th>
</tr>
</thead>
<tbody>
<tr>
<td>00171 </td>
<td>SŁUP 50/1800 POŚREDNI(P) </td>
<td>5</td><td>97.00 PLN </td>
<td>394.31 PLN </td>
</tr>
<tr>
<td>00172</td>
<td>SŁUP 50/1800 NAROŻNY(P)</td>
<td>1</td><td>97.00 PLN</td>
<td>78.86 PLN</td>
</tr>
<tr>
<td>00173 </td>
<td>SŁUP 50/1800 KOŃCOWY(P) </td>
<td>1</td><td>97.00 PLN </td>
<td>78.86 PLN</td>
</tr>
</tbody>
<tfoot style="font-weight: bold;">
<tr>
<th colspan="3" style="text-align: right;">Razem netto: 1955.85 PLN</th>
<th colspan="2" style="text-align: right;">Razem brutto: 2405.69 PLN</th>
</tr>
</tfoot>
</table>
and what i need is json object in this format (first <td> and third <td>):
[{"00171":5},
{"00172":1},
{"00173":1}
]
and that i can send it via
$.post(
"print.php",
{json: myjsonvar},
"json"
);
any idea how to do that?
thanks
var json = [];
$('#Report').find('tbody tr').each(function(){
var obj = {},
$td = $(this).find('td'),
key = $td.eq(0).text(),
val = parseInt( $td.eq(2).text(), 10 );
obj[key] = val;
json.push(obj);
});
How about:
var myjsonvar=[];
$('#Report tbody tr').each(function(){
var data={};
var tr=$(this);
data[tr.find('td:first-child').text()]=tr.find('td:nth-child(3)').text();
myjsonvar.push(data);
});
var sendData = [];
$('#Report tbody tr').each(function(i, el){
var key = $.trim($(this).find('td:eq(0)').text()),
val = $.trim($(this).find('td:eq(2)').text()),
obj = {};
obj[key] = val;
sendData.push(obj);
});
See demo
Why json, if you are in js already? Just create a simple object:
var data = {};
$("#Report tbody tr").each(function() {
data[$(this).children("td:eq(0)").text()] = $(this).children("td:eq(2)").text();
});
$.post("print.php", data);
Setting type to json in $.post defines the server response to be json, not the send data!
http://jsfiddle.net/zyCPN/
var objArray=[];
$('table#Report tbody tr').each(function(i){
var row=$(this);
obj={};
obj[$('td', row).eq(0).text()]=$('td', row).eq(2).text();
objArray.push(obj);
});

Sorting tbody elements by column value with jQuery

I am trying to sort a table - so when a user clicks on the table heading, it will sort in ascending/descending order. I've got it to the point where I can sort the table based on the column value. However, I have groupings of table rows (two rows per table body), and I want to sort the columns based on the values in the columns of the first row of each table body, but when it reorders the table, it want it to reorder the table bodies, not the table rows.
<table width="100%" id="my-tasks" class="gen-table">
<thead>
<tr>
<th class="sortable"><p>Name</p></th>
<th class="sortable"><p>Project</p></th>
<th class="sortable"><p>Priority</p></th>
<th class="sortable"><p>%</p></th>
</tr>
</thead>
<tbody>
<tr class="sortable-row" id="44">
<td><p>dfgdf</p></td><td><p>Test</p></td>
<td><p>1</p></td><td><p>0</p></td>
</tr>
<tr>
<td></td>
<td colspan="3"><p>asdfds</p></td>
</tr>
</tbody>
<tbody>
<tr class="sortable-row" id="43">
<td><p>a</p></td>
<td><p>Test</p></td>
<td><p>1</p></td>
<td><p>11</p></td>
</tr>
<tr>
<td></td>
<td colspan="3"><p>asdf</p></td>
</tr>
</tbody>
<tbody>
<tr class="sortable-row" id="40">
<td><p>Filter Tasks</p></td>
<td><p>Propel</p></td>
<td><p>10</p></td>
<td><p>10</p></td>
</tr>
<tr>
<td></td>
<td colspan="3"><p>Add a button to filter tasks.</p></td>
</tr>
</tbody>
</table>
With the following javascript:
jQuery(document).ready(function () {
jQuery('thead th').each(function(column) {
jQuery(this).addClass('sortable').click(function() {
var findSortKey = function($cell) {
return $cell.find('.sort-key').text().toUpperCase() + ' ' + $cell.text().toUpperCase();
};
var sortDirection = jQuery(this).is('.sorted-asc') ? -1 : 1;
var $rows = jQuery(this).parent().parent().parent().find('.sortable-row').get();
jQuery.each($rows, function(index, row) {
row.sortKey = findSortKey(jQuery(row).children('td').eq(column));
});
$rows.sort(function(a, b) {
if (a.sortKey < b.sortKey) return -sortDirection;
if (a.sortKey > b.sortKey) return sortDirection;
return 0;
});
jQuery.each($rows, function(index, row) {
jQuery('#propel-my-tasks').append(row);
row.sortKey = null;
});
jQuery('th').removeClass('sorted-asc sorted-desc');
var $sortHead = jQuery('th').filter(':nth-child(' + (column + 1) + ')');
sortDirection == 1 ? $sortHead.addClass('sorted-asc') : $sortHead.addClass('sorted-desc');
jQuery('td').removeClass('sorted').filter(':nth-child(' + (column + 1) + ')').addClass('sorted');
});
});
});
You need to sort the tbody elements, not the row elements. You said that yourself in your description of the problem, but your code actually sorts rows, not tbodies.
A secondary problem is that your sort treats everything as a string, which breaks when sorting 1-digit numeric strings ("2") against two-digit strings ("10").
To fix, replace this:
var $rows = jQuery(this).parent().parent().parent()
.find('.sortable-row').get();
jQuery.each($rows, function(index, row) {
row.sortKey = findSortKey(jQuery(row).children('td').eq(column));
});
with this:
var $tbodies = jQuery(this).parent().parent().parent()
.find('.sortable-row').parent().get();
jQuery.each($tbodies, function(index, tbody) {
var x = findSortKey(jQuery(tbody).find('tr > td').eq(column));
var z = ~~(x); // if integer, z == x
tbody.sortKey = (z == x) ? z : x;
});
And then replace $rows with $tbodies throughout your script, and row with tbody.
Example:
http://jsbin.com/oxuva5
I highly recommend the jQuery plugin http://tablesorter.com/ instead of rolling your own.
It's fully featured and well supported.

Categories