Jquery Collapsing Category - javascript

I'm currently try to make a collapsible category list using html table tag and jquery.
This is my jquery :
(function() {
var toggle = $('span.toggle');
toggle.on('click', function() {
var $this = $(this);
var objectClass = $this.parent().parent().attr('class');
toggleRow($this, objectClass);
});
function toggleRow(element, elClass) {
var classes = elClass.split(' ');
var textList = '';
for (var i = 0; i < classes.length; i++) {
if (classes[i].length > 0) {
textList += "."+classes[i];
}
}
var $this = element.parents(textList);
var lastRow = $this.index() == $('tr' + textList).last().index() ? true : false;
if($this.attr('data-collapse') !== 'collapsed') {
if(!lastRow) {
$this.attr('data-collapse', 'collapsed').nextUntil('tr' + textList).hide();
} else {
$this.attr('data-collapse', 'collapsed').nextUntil('tr.has-children').hide();
}
} else {
if(!lastRow) {
$this.attr('data-collapse', '').nextUntil('tr' + textList).show();
} else {
$this.attr('data-collapse', '').nextUntil('tr.has-children').show();
}
}
}
}());
this is my HTML :
<table class="table table-bordered" id="MainMenu">
<thead>
<tr>
<th width="50">No</th>
<th>Category Name</th>
</tr>
</thead>
<tbody>
<tr class="parent-row has-children" data-collapse="">
<td>1</td>
<td>
<span class="toggle"><i class="fa fa-fw fa-caret-down"></i></span>Dog
</td>
</tr>
<tr class="child-row" data-collapse="">
<td>2</td>
<td>
<span class="toggle"><i class="fa fa-fw fa-caret-down"></i></span>Foods and Treats
</td>
</tr>
<tr class="child-child-row">
<td>3</td>
<td>
Dry Food
</td>
</tr>
<tr class="parent-row has-children" data-collapse="">
<td>1</td>
<td>
<span class="toggle"><i class="fa fa-fw fa-caret-down"></i></span>Dog
</td>
</tr>
<tr class="child-row" data-collapse="">
<td>2</td>
<td>
<span class="toggle"><i class="fa fa-fw fa-caret-down"></i></span>Foods and Treats
</td>
</tr>
<tr class="child-child-row">
<td>3</td>
<td>
Dry Food
</td>
</tr>
</tbody>
</table>
Now the problem is when i click tr tag with "child-row" class, the jquery collapse UNTIL THE NEXT tr tag WITH "child-row" CLASS !
so if there is tr tag with "parent-row" class between 2 tr tag with class "child-row", its also closed.
I found the problem in my Jquery but i cannot fixed it, it was in this row :
var lastRow = $this.index() == $('tr' + textList).last().index() ? true : false;
it will always return false, except for the LAST tr tag WITH CLASS "child-row" in the table
I know my explanation is kinda blur, i make a fiddle here :
JsFiddle
but i'm also kinda new to JsFiddle, i even cannot make my code work there.
So, i someone knew how to fix this code, please reply. Thanks.

Related

jquery - show / hide elements rows by elemenst in data-id array

I have table with rows like that:
<tr class="listRow" data-id="[11,0]">...</tr>
<tr class="listRow" data-id="[1,2,3]">...</tr>
How i can using JQuery filter specific rows with element in array? For example by button click show all rows with 1 in array and hide rest.
Edit - my sample code so far:
i don't know how to filtering elements in data-id array.
$(document).on('click','#filterList',function()
{
var element = $(this).data("id");
// how to filter elements in rows
}
);
If i understand correctly:
$('#check').click(function() {
$('.listRow').each(function() {
if($.inArray(1, $(this).data().id)>-1) {
$(this).show();
}
else {
$(this).hide()
}
});
});
$('#check').click(function() {
$('.listRow').each(function() {
if($.inArray(1, $(this).data().id)>-1) {
$(this).show();
}
else {
$(this).hide()
}
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table class="tg">
<thead>
<tr class="listRow" data-id="[1,0]">
<th class="tg-0pky">Here is 1</th>
<th class="tg-0pky">xxxx</th>
<th class="tg-0pky"></th>
<th class="tg-0pky"></th>
</tr>
</thead>
<tbody>
<tr class="listRow" data-id="[11,0]">
<td class="tg-0pky">Not 1</td>
<td class="tg-0pky"></td>
<td class="tg-0pky"></td>
<td class="tg-0pky"></td>
</tr>
<tr class="listRow" data-id="[15,0]" >
<td class="tg-0pky">Not 1</td>
<td class="tg-0pky"></td>
<td class="tg-0pky"></td>
<td class="tg-0pky"></td>
</tr>
<tr class="listRow" data-id="[1,0,3]">
<td class="tg-0pky" >Here is 1</td>
<td class="tg-0pky"></td>
<td class="tg-0pky"></td>
<td class="tg-0pky"></td>
</tr>
</tbody>
</table>
<button id="check">
Click
</button>
when you press the button, loop through all the elements that have a data-id
parse the data-id as json, which will give you an array
if the array includes the id you're looking for, set the class to hide or show (where they have the display css assigned accordingly)
here's what that might look like without jquery and using style and opacity. Usually it's done using class but this is for demonstration purposes, changing to use classes should be straight forward.
function findElsById(id){
var matches = []
document.querySelectorAll('[data-id]').forEach(function(el){
try{
var arr = JSON.parse(el.dataset.id)
if (arr.includes(id)) matches.push(el)
} catch (e){
// prolly not valid json
}
})
return matches
}
function show(id){
var els = findElsById(id);
console.log('show', id, '\nshowing: ', els)
if (els) {
els.forEach(function(el){
el.style = 'opacity:1'
})
}
}
function hide(id){
var els = findElsById(id);
console.log('hide', id, '\nhiding: ', els)
if (els) {
els.forEach(function(el){
el.style = 'opacity:0.1'
})
}
}
<table>
<tr class="listRow" data-id="[1,0]"><td>1, 0</td></tr>
<tr class="listRow" data-id="[1,2]"><td>1, 2</td></tr>
</table>
<button onclick="hide(0)">-0</button>
<button onclick="hide(1)">-1</button>
<button onclick="hide(2)">-2</button>
<button onclick="show(0)">+0</button>
<button onclick="show(1)">+1</button>
<button onclick="show(2)">+2</button>

How do I get and pass the field of the row having class="name" in the following html?

<tbody>
<tr>
<td>gibberish</td>
<td class="name" hidden>200398</td>
<td>iPhone X 64Gb Grey</td>
<td>$999.00</td>
<td>1</td>
<td>
<button onclick="fetchdata(parameter)">Fetch Details</button>
</td>
</tr>
</tbody>
In the above html, I want that the function fetchdata('parameter') to contain the text content of the td which has a class of name and is hidden, as the parameter.
OR
I need a way in which I can get the text content of the td having class of name in my javascript function.
i.e.
function fetchdata() {
const name = document.somethingThatGivesMeName()
}
NOTE: There are going to be multiple rows that I may require to get the name of so I can't directly do document.queryselector('.name')
Sorry, This might be pretty simple but I can't quite figure it out.
When clicking the button find the first row up in the tree relative to the button with the closest method. Then from the row select the element with the class name and read the textContent or innerText of that element.
const buttons = document.querySelectorAll('.js-fetch-details');
function fetchDetails(event) {
const row = event.target.closest('tr');
const name = row.querySelector('.name').textContent;
console.log(name);
}
buttons.forEach(button => button.addEventListener('click', fetchDetails));
<table>
<tbody>
<tr>
<td>gibberish</td>
<td class="name" hidden>200398</td>
<td>iPhone X 64Gb Grey</td>
<td>$999.00</td>
<td>1</td>
<td>
<button class="js-fetch-details">Fetch Details</button>
</td>
</tr>
</tbody>
</table>
You just need the quotes ':
function fetchdata(value){
console.log(value)
}
<tbody>
<tr>
<td>gibberish</td>
<td class="name" hidden>200398</td>
<td>iPhone X 64Gb Grey</td>
<td>$999.00</td>
<td>1</td>
<td>
<button onclick="fetchdata('parameter')">Fetch Details</button>
</td>
</tr>
</tbody>
or you can use event listener and data value:
document.querySelectorAll('button').forEach(el => {
el.addEventListener('click', e => {
e = e || window.event;
e = e.target || e.srcElement;
console.log(e.dataset.value)
})
})
<tbody>
<tr>
<td>gibberish</td>
<td class="name" hidden>200398</td>
<td>iPhone X 64Gb Grey</td>
<td>$999.00</td>
<td>1</td>
<td>
<button data-value="parameter">Fetch Details</button>
</td>
</tr>
</tbody>
You can use document.getElementsByClassName('name')
This will get all the elements that have class of name.
I would put the listener on the <tbody> instead.
document.querySelector('tbody').addEventListener('click', (e) => {
// Clicking on the whole row
if (e.target.nodeName === 'TR') {
const name = e.target.querySelector('.name').textContent;
console.log(name);
}
// Clicking on the button
// Give the button a class
if (e.target.classList.contains('.somebuttonclass')) {
const name = e.target.parentNode.parentNode.querySelector('.name').textContent;
console.log(name);
}
});
UPDATE
closest would also work
document.querySelector('tbody').addEventListener('click', (e) => {
// Clicking on the whole row
if (e.target.nodeName === 'TR') {
const name = e.target.querySelector('.name').textContent;
console.log(name);
}
// Clicking on the button
// Give the button a class
if (e.target.classList.contains('.somebuttonclass')) {
const name = e.target.closest('tr').querySelector('.name').textContent;
console.log(name);
}
});
First you get all elements with class="name", then you pick just (the first) one with the attribute "hidden".
It's a way to do it anyway.
function fetchdata() {
const tds = document.getElementsByClassName("name")
for(let i = 0; i < tds.length; i++){
if(tds[i].getAttribute("hidden") != null) {
console.log(tds[i].innerHTML)
}
}
}
<table>
<tr>
<td class="name">gibberish</td>
<td class="name" hidden>200398</td>
<td>iPhone X 64Gb Grey</td>
<td>$999.00</td>
<td class="name">1</td>
<td>
<button onclick="fetchdata()">Fetch Details</button>
</td>
</tr>
</table>
With jQuery you can just do:
function fetchdata() {
console.log($('.name[hidden]').html());
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table>
<tr>
<td>gibberish</td>
<td class="name" hidden>200398</td>
<td>iPhone X 64Gb Grey</td>
<td>$999.00</td>
<td>1</td>
<td>
<button onclick="fetchdata()">Fetch Details</button>
</td>
</tr>
</table>
Note that you need to have a table around your structure for any of this to work properly. You can't have tbody, tr and td outside a table.
If you use document.getElementsByClassName you will get what you want.
However, if there will be a case where more than one instance of that class name will occur, then you need to iterate through the classes and get their values.
The following should solve your problem
<html>
<head>
<script>
function fetchdata(){
var data = document.getElementsByClassName("data");
var t = data.length;
for(i = 0; i< t; i++){
var content = data[i].innerHTML;
alert (content);
}
}
</script>
<body>
<table>
<tbody>
<tr>
<td>gibberish</td>
<td class="data" hidden>200398</td>
<td>iPhone X 64Gb Grey</td>
<td>$999.00</td>
<td>1</td>
<td>
<button onclick="fetchdata()">Fetch Details</button>
</td>
</tr>
</tbody>
</table>
</body>
</html>

Collapsing and expanding multiple nested rows in jQuery

I need a little help with collapsing and expanding nested rows. Currently my code below expands and collapses as desired at the first level but the subsequent levels also show.
$(document).ready(function(e) {
$('.collapseTitle').click(function() {
$(this).parent()
.parent()
.next('tbody')
.toggleClass('collapsed');
});
});
.collapsed {
display: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table>
<thead>
<tr>
<td class="collapseTitle">Title</td>
</tr>
</thead>
<tbody class="collapsed">
<tr>
<td>Level 1</td>
</tr>
<tr>
<td>Level 2</td>
</tr>
</tbody>
</table>
I am trying to achieve that Level 1 expands when "collapseTitle" is clicked and that only when "collapseAccount" is clicked, does Level 2 expand. Now I know that my code should look something like the below, but I am struggling...
<table>
<thead>
<tr>
<td class="collapseTitle">Title</td>
</tr>
</thead>
<tbody>
<tr class="collapsed account">
<td class="collapseAccount">Level 1</td>
</tr>
<tr class="collapsed level">
<td>Level 2</td>
</tr>
</tbody>
</table>
<script>
$(document).ready(function(e) {
$('.collapseTitle').click(function() {
$(this).parent().parent().next('tbody tr').toggleClass('account');
});
});
$(document).ready(function(e) {
$('.collapseAccount').click(function() {
$(this).next('tr').toggleClass('level');
});
});
</script>
Any help would be greatly appreciated.
The following code should do it. I hope it helps with what you want to achieve:
collapses/expands columns when clicking on the header/title of the column and
collapses/expands all rows following the account row when clicking on it (until the next account row)
The only thing you need to do is add the class account to the higher level rows. You can do this pretty easily when you're displaying these with a loop.
.collapsed {
/* using visibility, since display causes layout issues */
/* due to empty rows rows/columns collapsing */
visibility: collapse;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table>
<thead>
<tr>
<td>Title1</td>
<td>Title2</td>
</tr>
</thead>
<tbody>
<tr class="account">
<td class="collapsed">Account Summary - Account A</td>
<td class="collapsed">Account Summary - Account A</td>
</tr>
<tr class="collapsed">
<td class="collapsed">Account Details Part I - Account A</td>
<td class="collapsed">Account Details Part I - Account A</td>
</tr>
<tr class="collapsed">
<td class="collapsed">Account Details Part II - Account A</td>
<td class="collapsed">Account Details Part II - Account A</td>
</tr>
<tr class="account">
<td class="collapsed">Account Summary - Account B</td>
<td class="collapsed">Account Summary - Account B</td>
</tr>
<tr class="collapsed">
<td class="collapsed">Account Details Part I - Account B</td>
<td class="collapsed">Account Details Part I - Account B</td>
</tr>
</tbody>
</table>
<script>
$(document).ready(() => {
/* the following handlers expand/collapse the columns */
$('thead > tr > td').each((i, el) => {
$(el).click(() => {
const colIndex = $(el).index() + 1;
const nRows = $('tbody > tr').length;
for (let j = 0; j < nRows; j += 1) {
let cellSelector = `tbody > tr:nth-child(${j+1})`
cellSelector += `> td:nth-child(${colIndex})`;
$(cellSelector).toggleClass('collapsed');
}
})
})
/* the following handlers expand/collapse the account-details rows */
$('tbody > tr.account').each((i, el) => {
$(el).click(() => {
$(el).nextUntil('.account').each((j, ele) => {
$(ele).toggleClass('collapsed');
})
})
})
});
</script>
Your jQuery selectors are just a bit off for the toggleClass. You can use the class names of the row to toggle. Also you should create a class to be toggled that displays the row/hides it. For example:
edit:
I now created the titles and rows dynamically to give you a better idea of how this can be done using data- attributes.
You will have a title td and a row td that match on a data- attribute, so when you click a title and corresponding tr will be shown. So for example if you click title 1 (with a data-index=1) then the tr with the attribute data-rowindex=1 will be shown.
$(document).ready(function(e) {
createTable();
$('.collapseTitle').click(function() {
// grab the data-index value from the clicked title
let index = $(this).attr("data-index");
// find a tr that has the attribute data-rowindex and it matches index
$("tr[data-rowindex='" + index + "']").toggleClass("collapsed");
});
});
function createTable(){
// create the titles and the level rows
for(let i = 0; i < 3; i++){
// create the title row
let $trTitle = $('<tr>');
let $tdTitle = $('<td>', {class: "collapseTitle", text: "Title " + i});
$tdTitle.attr("data-index", i);
let $finalTitleRow = $trTitle.append( $tdTitle );
// create the level row
let $trLevel = $('<tr>', {class: "collapsed account"} );
$trLevel.attr("data-rowindex", i);
let $tdLevel = $('<td>', {text: "Level " + i});
let $finalLevelRow = $trLevel.append( $tdLevel );
// add the title and level row pairs to the head and body
$("#myTableHead").append($finalTitleRow[0]);
$("#myTableBody").append($finalLevelRow[0]);
}
}
.collapsed {
display: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table>
<thead id="myTableHead">
</thead>
<tbody id="myTableBody">
</tbody>
</table>
I managed to find the answer I was looking for... Thank you to "stackoverfloweth",
Answer To My Question
The snippet of code which has helped me thus far is below,
$('.parent-row').click(function(){
var $element = $(this).next();
while(!$element.hasClass('parent-row')){
$element.toggle();
if($element.next().length >0){
$element = $element.next();
}
else{
return;
}
} });
$('.child-row.has-children').click(function(){
var $element = $(this).next();
while($element.hasClass('child-child-row')){
$element.toggle();
if($element.next().length >0){
$element = $element.next();
}
else{
return;
}
} });

Hide a tr only if td contains no content AFTER a specific html tag

Is it possible to examine the content within a tr, AFTER an html element (br) to see if any exists? If there is no content after the br element, I'd like to hide the parent td. Please note that the html code is system generated and I cannot edit it.
I'm just not sure where to begin with this. Any help is greatly appreciated.
<table class="tabledefault">
<tbody>
<tr>
<td id="customfields">
<table class="tabledefault">
<tbody>
<tr><!-- this TR should be hidden -->
<td id="CAT_Custom_451068"><strong>Laser Tag</strong>
<br>
</td>
</tr>
<tr>
<td id="CAT_Custom_451069"><strong>Arcade</strong>
<br>Selected
</td>
</tr>
<tr>
<td id="CAT_Custom_450908"><strong>Bounce House (45 minutes) $100</strong>
<br>False
</td>
</tr>
<tr>
<td id="CAT_Custom_451307"><strong>Party Room Rental (per hour) $75</strong>
<br>True</td>
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table>
Try using .each() , nextSibling , nodeValue , String.prototype.match() , .closest()
$("table tr td br").each(function(i, el) {
// if `br` next sibling does not contain alphanumeric characters,
// hide parent `tr` element
if (el.nextSibling.nodeType === 3
&& el.nextSibling.nodeValue.match(/\w+/) === null
|| $(el).next(":empty").length) {
$(this).closest("tr").hide()
}
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js">
</script>
<table class="tabledefault">
<tbody>
<tr>
<td id="customfields">
<table class="tabledefault">
<tbody>
<tr><!-- this TR should be hidden -->
<td id="CAT_Custom_451068"><strong>Laser Tag</strong>
<br><span></span>
</td>
</tr>
<tr>
<td id="CAT_Custom_451069"><strong>Arcade</strong>
<br>Selected
</td>
</tr>
<tr>
<td id="CAT_Custom_450908"><strong>Bounce House (45 minutes) $100</strong>
<br>False
</td>
</tr>
<tr>
<td id="CAT_Custom_451307"><strong>Party Room Rental (per hour) $75</strong>
<br>True</td>
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table>
Yes, you just get the trs, then find out if the first <br> element inside the first <td> has any following element siblings (I'm making an assumption there, that you don't want those hidden), or any following text node siblings that aren't blank. jQuery's contents is handy for that, as it includes text nodes. I'd probably loop through them backward:
$("#customfields .tabledefault tr").each(function(index) {
var $tr = $(this);
$tr.find("td:first").contents().get().reverse().some(function(node) {
if (node.nodeName.toUpperCase() === "BR") {
// Hide it, and we're done looping
$tr.hide();
return true;
}
if (node.nodeType != 3 || $.trim(node.nodeValue)) {
// Don't hide it, and we're done looping
return true;
}
});
});
I expect that can be optimized, but you get the idea.
Live Example:
var counter = 3;
tick();
function tick() {
$("#countdown").text(counter--);
if (counter < 0) {
hideIt();
} else {
setTimeout(tick, 500);
}
}
function hideIt() {
$("#customfields .tabledefault tr").each(function(index) {
var $tr = $(this);
$tr.find("td:first").contents().get().reverse().some(function(node) {
if (node.nodeName.toUpperCase() === "BR") {
// Hide it, and we're done looping
$tr.hide();
return true;
}
if (node.nodeType != 3 || $.trim(node.nodeValue)) {
// Don't hide it, and we're done looping
return true;
}
});
});
}
<table class="tabledefault">
<tbody>
<tr>
<td id="customfields">
<table class="tabledefault">
<tbody>
<tr>
<!-- this TR should be hidden -->
<td id="CAT_Custom_451068"><strong>Laser Tag</strong>
<br>
</td>
</tr>
<tr>
<td id="CAT_Custom_451069"><strong>Arcade</strong>
<br>Selected
</td>
</tr>
<tr>
<td id="CAT_Custom_450908"><strong>Bounce House (45 minutes) $100</strong>
<br>False
</td>
</tr>
<tr>
<td id="CAT_Custom_451307"><strong>Party Room Rental (per hour) $75</strong>
<br>True</td>
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div id="countdown"> </div>

How to copy the contents of one row in a table to another table and add the identical ones

var Sell_Button = document.getElementById('sellbtn'),
secondTable = document.getElementById("secondTableBody");
Sell_Button.addEventListener('click', function() {
var Row = secondTable.insertRow();
for (var c = 0; c < 2; c += 1) {
Row.insertCell(c);
}
Row.cells[0].innerHTML = this.parentNode.parentNode.cells[0].innerHTML;
Row.cells[2].innerHTML = this.parentNode.parentNode.cells[1].innerHTML;
//checks to see if the secondTable has a row containing the same name
for (var f = 0; f < secondTable.rows.length; f += 1) {
//adds only the sold amount if the second table has a row with the same name
//error
if (secondTable.rows[f].cells[0].innerText === this.parentNode.parentNode.cells[0].innerText) {
secondTable.rows[f].cells[1].innerHTML = +this.parentNode.parentNode.cells[2].innerHTML;
//deletes an extra row that is added at the bottom
if (secondTable.rows.length > 1) {
secondTable.deleteRow(secondTable.rows.length - 1);
}
//if nothing matched then a new row is added
} else {
secondTable.insertRow();
Row.cells[0].innerHTML = this.parentNode.parentNode.cells[0].innerHTML;
Row.cells[1].innerHTML = this.parentNode.parentNode.cells[2].innerHTML;
}
}
}
}
<html>
<body>
<div id="firstTableDiv">
<table border="1" id="firstTable">
<thead>
<th>Item</th>
<th>Stock</th>
<th colspan="1">Sold</th>
</thead>
<tbody id="firstTableBody">
<tr>
<td>Apples</td>
<td>300</td>
<td>200</td>
<td>
<button id="sellbtn">Sell</button>
</td>
</tr>
<tr>
<td>Apples</td>
<td>300</td>
<td>100</td>
<td>
<button id="sellbtn">Sell</button>
</td>
</tr>
<tr>
<td>Oranges</td>
<td>400</td>
<td>300</td>
<td>
<button id="sellbtn">Sell</button>
</td>
</tr>
</tbody>
</table>
</div>
</br>
<div id="secondTableDiv">
Sold
<table border="1" id="secondTable">
<thead>
<th>Item</th>
<th>Sold</th>
</thead>
<tbody id="secondTableBody">
</tbody>
</table>
</div>
</body>
</html>
Ok, this example isn't exactly what i'm working on but it's very similar. The only difference is that in mine the rows and buttons are dynamically added by the user and he inserts the details. What I want is that when i press on the button of each row (sell) the details (Item and Sold only) are copied into a row in the second table and checks if the same item exists in this second table if so then it adds the amount of sold of both items in one row. For instance I press on the first row button the Apples it copies the listed above details to the second table in a row and then when i click on the button of the second row (Apples also) it only adds the sold amount up and doesn't add a second apples row because an apples row already exists in the second table but when i click on the oranges button it makes a new row because the oranges row doesn't exist. So how do I do this in JavaScript? i hope i was thorough and made any sense. I have no idea why the code isn't working here but i hope you get the point. This code works perfectly just as i want it to until for some reason i get this error: Cannot read property 'innerText' of undefined when i press the buttons approx. 6-7 times targeting the if statement where i commented error.
This sets a click handler to all buttons. If the row doesn't exist in the second table it's created. It sets a data-type referring to the item. When somebody clicks the sell button again and there is a row containing the data-type the row is updated instead of created. All in plain JavaScript.
var Sell_Button = document.querySelectorAll('.sellbtn'),
secondTable = document.getElementById("secondTableBody");
Array.prototype.slice.call(Sell_Button).forEach(function(element){
element.addEventListener('click', function(e) {
//since the button is an element without children use e.
var clickedElement = e.target;
var parentRow = clickedElement.parentNode.parentNode;
//check if second table has a row with data-type
var rowWithData = secondTable.querySelector("[data-type='"+parentRow.cells[0].childNodes[0].nodeValue+"']");
if (rowWithData)
{
rowWithData.cells[1].innerHTML = parseInt(rowWithData.cells[1].childNodes[0].nodeValue) + parseInt(parentRow.cells[2].childNodes[0].nodeValue);
}
else
{
var Row = secondTable.insertRow();
Row.setAttribute("data-type", parentRow.cells[0].childNodes[0].nodeValue);
for (var c = 0; c < 2; c += 1) {
Row.insertCell(c);
}
Row.cells[0].innerHTML = parentRow.cells[0].childNodes[0].nodeValue;
Row.cells[1].innerHTML = parentRow.cells[2].childNodes[0].nodeValue;
}
});
});
<html>
<body>
<div id="firstTableDiv">
<table border="1" id="firstTable">
<thead>
<th>Item</th>
<th>Stock</th>
<th colspan="1">Sold</th>
</thead>
<tbody id="firstTableBody">
<tr>
<td>Apples</td>
<td>300</td>
<td>200</td>
<td>
<button class="sellbtn">Sell</button>
</td>
</tr>
<tr>
<td>Apples</td>
<td>300</td>
<td>100</td>
<td>
<button class="sellbtn">Sell</button>
</td>
</tr>
<tr>
<td>Oranges</td>
<td>400</td>
<td>300</td>
<td>
<button class="sellbtn">Sell</button>
</td>
</tr>
</tbody>
</table>
</div>
</br>
<div id="secondTableDiv">
Sold
<table border="1" id="secondTable">
<thead>
<th>Item</th>
<th>Sold</th>
</thead>
<tbody id="secondTableBody">
</tbody>
</table>
</div>
</body>
</html>
Do you mean something like:
$(document).on("click", "#firstTable tr button", function(b) {
b = $(this).closest("tr");
var d = $.trim(b.find("td:first").text());
b = parseFloat($.trim(b.find("td:nth-child(3)").text()));
var a = $("#secondTable"),
c = a.find("tr").filter(function(a) {
return $.trim($(this).find("td:first").text()) == d
});
c.length ? (a = c.find("td:nth-child(2)"), c = parseFloat($.trim(a.text())), a.text(b + c)) : (a = $("<tr />").appendTo(a), $("<td />", {
text: d
}).appendTo(a), $("<td />", {
text: b
}).appendTo(a))
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<div id="firstTableDiv">
<table border="1" id="firstTable">
<thead>
<tr>
<th>Item</th>
<th>Stock</th>
<th colspan="1">Sold</th>
</tr>
</thead>
<tbody id="firstTableBody">
<tr>
<td>Apples</td>
<td>300</td>
<td>200</td>
<td><button>Sell</button></td>
</tr>
<tr>
<td>Apples</td>
<td>300</td>
<td>100</td>
<td><button>Sell</button></td>
</tr>
<tr>
<td>Oranges</td>
<td>400</td>
<td>300</td>
<td><button>Sell</button></td>
</tr>
</tbody>
</table>
</div>
<br />
<div id="secondTableDiv">
Sold
<table border="1" id="secondTable">
<thead>
<tr>
<th>Item</th>
<th>Sold</th>
</tr>
</thead>
<tbody id="secondTableBody"></tbody>
</table>
</div>

Categories

Resources