Problem with Expanding and shrinking Table on load - javascript

I am revising the code to better match the HTML table that mplungjan created below. However I am keeping the FOR loops as this is how I am generating the tables.
<table>
<thead>
<th style="text-align:center">Expand</th>
</thead>
{% for supply in supplylist %}
<tbody>
<tr>
<td data-toggle="toggle">
<p>+</p>
</td>
Here is problem I am trying to solve:
When clicking the link above, I want to write either a + or - to this variable below supply[0]
When loading the form, I want to read the value from this same variable and either shrink or expand the specific row based on whether its value is '+' or '-'
Is there a Java Script that I can use to read this variable on load and either shrink or expand the row as applicable.
And is there a Java Script that I can use to write either a + or - to this variable whenever the user clicks the link.
<td style="display:none"><input name="expand" value="{{supply[0]}}"></td>
</tr>
</tbody>
<tbody class="hideTr">
{% for number in supply[5] %}
<tr>
<td>To be hidden {{number}}</td>
</tr>
<tr>
<td>To be hidden</td>
</tr>
<tr>
<td>To be hidden</td>
</tr>
{% endfor %}
</tbody>
{% endfor %}
</table>
I am revising the Script to use mplungjan's example below as well, since this script also works and is more modern.
<script>
const toggleTbody = function() {
const $tbodyToToggle = $(this).closest('tbody').next(".hideTr");
$tbodyToToggle.toggle()
const visible = $tbodyToToggle.is(":visible")
$(this).text(visible ? '-' : '+')
}
$(document).ready(function() {
$('.plusminusexpands')
.on('click',toggleTbody)
.each(function() {
if ($(this).text() === "+") $(this).click()
})
});
</script>

Lacking the expected example HTML, I produced my own
I added a tbody to the toggle rows
You can now set the plus or minus on the server and I use localStorage to not have to store the settings in a session
IDs need to be unique so I removed the ID and just use the class
Here is a version with localStorage - I use try/catch to run on SO because localStorage is sandboxed
$(document).ready(function() {
const $plusMinuses = $('.plusminusexpands'); // all the plusminusexpands
let savedPlusMinuses; // this will be the array we use
try { // stacksnippets do not like localStorage
savedPlusMinuses = localStorage.getItem("savedPlusMinuses");
savedPlusMinuses = savedPlusMinuses ? JSON.parse(savedPlusMinuses) : [];
}
catch {
console.log("no localStorage available");
savedPlusMinuses = []; // set to empty array
}
// here we gather default values in case of first visit
if (savedPlusMinuses.length === 0) savedPlusMinuses = $plusMinuses.map(function() {
return this.textContent.trim()
}).get(); // get the current set of plusminus
const toggleTbody = function() {
const $tbodyToToggle = $(this).closest('tbody').next(".hideTr");
$tbodyToToggle.toggle()
const visible = $tbodyToToggle.is(":visible")
$(this).text(visible ? '-' : '+')
savedPlusMinuses[$(this).data("idx")] = $(this).text()
console.log(savedPlusMinuses.join("")); // debugging
// localStorage.setItem("savedPlusMinuses",JSON.stringify(savedPlusMinuses)); // uncomment
};
// set the event handler on the plusminues and then loop to initialise the DOM
$plusMinuses
.on('click', toggleTbody)
.each(function(i) { // looping all the plus/minuses to set the state
$(this).text(savedPlusMinuses[i]) // initialise with saved values
.data("idx", i); // set a data-attribute to find it quickly when saving
if ($(this).text() === "+") $(this).click()
})
});
.plusminusexpands {
text-decoration: none;
font-size: x-large
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table>
<thead>
<th style="text-align:center">Expand</th>
</thead>
<tbody>
<tr>
<td data-toggle="toggle">
<p>+</p>
</td>
<td style="display:none"><input name="expand" value="{{supply[0]}}"></td>
</tr>
</tbody>
<tbody class="hideTr">
<tr>
<td>To be hidden 1</td>
</tr>
<tr>
<td>To be hidden</td>
</tr>
<tr>
<td>To be hidden</td>
</tr>
</tbody>
<tbody>
<tr>
<td data-toggle="toggle">
<p>-</p>
</td>
<td style="display:none"><input name="expand" value="{{supply[0]}}"></td>
</tr>
</tbody>
<tbody class="hideTr">
<tr>
<td>To be hidden 2</td>
</tr>
<tr>
<td>To be hidden</td>
</tr>
<tr>
<td>To be hidden</td>
</tr>
</tbody>
<tbody>
<tr>
<td data-toggle="toggle">
<p>+</p>
</td>
<td style="display:none"><input name="expand" value="{{supply[0]}}"></td>
</tr>
</tbody>
<tbody class="hideTr">
<tr>
<td>To be hidden 3</td>
</tr>
<tr>
<td>To be hidden</td>
</tr>
<tr>
<td>To be hidden</td>
</tr>
</tbody>
</table>
Here is a version which would need to save the plusminusses using Ajax to the server
const toggleTbody = function() {
const $tbodyToToggle = $(this).closest('tbody').next(".hideTr");
$tbodyToToggle.toggle()
const visible = $tbodyToToggle.is(":visible")
$(this).text(visible ? '-' : '+')
}
$(document).ready(function() {
$('.plusminusexpands')
.on('click',toggleTbody)
.each(function() { // looping all the plus/minuses to set the state
if ($(this).text() === "+") $(this).click()
})
});
.plusminusexpands { text-decoration:none; font-size: x-large }
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table>
<thead>
<th style="text-align:center">Expand</th>
</thead>
<tbody>
<tr>
<td data-toggle="toggle">
<p>+</p>
</td>
<td style="display:none"><input name="expand" value="{{supply[0]}}"></td>
</tr>
</tbody>
<tbody class="hideTr">
<tr>
<td>To be hidden 1</td>
</tr>
<tr>
<td>To be hidden</td>
</tr>
<tr>
<td>To be hidden</td>
</tr>
</tbody>
<tbody>
<tr>
<td data-toggle="toggle">
<p>-</p>
</td>
<td style="display:none"><input name="expand" value="{{supply[0]}}"></td>
</tr>
</tbody>
<tbody class="hideTr">
<tr>
<td>To be hidden 2</td>
</tr>
<tr>
<td>To be hidden</td>
</tr>
<tr>
<td>To be hidden</td>
</tr>
</tbody>
<tbody>
<tr>
<td data-toggle="toggle">
<p>+</p>
</td>
<td style="display:none"><input name="expand" value="{{supply[0]}}"></td>
</tr>
</tbody>
<tbody class="hideTr">
<tr>
<td>To be hidden 3</td>
</tr>
<tr>
<td>To be hidden</td>
</tr>
<tr>
<td>To be hidden</td>
</tr>
</tbody>
</table>

Related

Accessing HTML Table cell and Change the value

I need to access the cell of an HTML Table and change Its value. The method I tried didn't worked out. Refer the screenshot as well.
Cannot use the following method, since there were multiple with same value in some cases. I need to access the specific marked cell.
$('td:contains("1200")').text('....');
Cell need to access and Change the amount
<table class="table table-striped">
<thead>
<tr>
<th>Loan amount</th>
<th>New loan installment amount (first installment)</th>
<th>DSCR (both new and existing)</th>
</tr>
</thead>
<tbody>
<tr>
<td id="ValueOne">LKR 12000</td>
<td>Doe</td>
<td>john#example.com</td>
</tr>
<tr>
<td>Mary</td>
<td>Moe</td>
<td>mary#example.com</td>
</tr>
<tr>
<td>July</td>
<td>Dooley</td>
<td>july#example.com</td>
</tr>
<tr>
<td>July</td>
<td>Dooley</td>
<td>july#example.com</td>
</tr>
<tr>
<td>July</td>
<td>Dooley</td>
<td>july#example.com</td>
</tr>
</tbody>
</table>
Accessing by ID And changing the value didn't worked.
document.getElementById("ValueOne").innerHTML = 'New Value';
Since you kindly provided us with an ID. Simply use:
Javascript:
document.getElementById("ValueOne").innerHTML = "LKR 100"
JQuery:
$("#ValueOne").text("LKR 100")
Demo: https://jsfiddle.net/fme8v6oa/
Options:
document.getElementsByTagName("td")[0].innerHTML = "LKR 100"
Your javascript code works, make sure to run your script after the page is loaded.
Here is an example using a button:
<table class="table table-striped">
<thead>
<tr>
<th>Loan amount</th>
<th>New loan installment amount (first installment)</th>
<th>DSCR (both new and existing)</th>
</tr>
</thead>
<tbody>
<tr>
<td id="ValueOne">LKR 12000</td>
<td>Doe</td>
<td>john#example.com</td>
</tr>
<tr>
<td>Mary</td>
<td>Moe</td>
<td>mary#example.com</td>
</tr>
<tr>
<td>July</td>
<td>Dooley</td>
<td>july#example.com</td>
</tr>
<tr>
<td>July</td>
<td>Dooley</td>
<td>july#example.com</td>
</tr>
<tr>
<td>July</td>
<td>Dooley</td>
<td>july#example.com</td>
</tr>
</tbody>
</table>
<button onclick="changeme()">Change</button>
<script>
function changeme(){
document.getElementById("ValueOne").innerHTML = 'New Value';
}
</script>
Using jquery :
$('#mytable tr').each(function() {
$(this).find("#ValueOne").html("new value");
});
where mytable is the Id of your table
Demo : https://jsfiddle.net/xLz6f49h/4/
<html>
<body>
<table class="table table-striped">
<thead>
<tr>
<th>Loan amount</th>
<th>New loan installment amount (first installment)</th>
<th>DSCR (both new and existing)</th>
</tr>
</thead>
<tbody>
<tr>
<td id="Value1">LKR 12000</td>
<td id="Value2">Doe</td>
<td id="Value2">john#example.com</td>
</tr>
<tr>
<td id="Value3">Mary</td>
<td id="Value4">Moe</td>
<td id="Value5">mary#example.com</td>
</tr>
<tr>
<td id="Value6">July</td>
<td id="Value7">Dooley</td>
<td id="Value8">july#example.com</td>
</tr>
<tr>
<td id="Value9">July</td>
<td id="Value10">Dooley</td>
<td id="Value11">july#example.com</td>
</tr>
<tr>
<td>July</td>
<td>Dooley</td>
<td>july#example.com</td>
</tr>
</tbody>
</table>
CELL id: <input type="text" name="celliD" id="input1"><br><br>
New CELL Value: <input type="text" name="celliD" id="input2"><br>
<button onclick="changeCellValue()">Change Value</button>
<script>
function changeCellValue(){
var inputVal = document.getElementById('input1').value;
var newVal = document.getElementById('input2').value;
if(inputVal == null || inputVal == "" && newVal == null || newVal == ""){
alert("value is required");
} else {
var changeVal = document.getElementById(inputVal).innerHTML = newVal;
}
}
</script>
<body>
</html>

Replace elements value of table

I know there was a billion questions like my but I still can't find solution, and I know it's basic and fundamentals of JS but I'm new with this language.
Ok, so I have table
<table>
<tr id = 'first'>
<th>#</th>
<th>Name</th>
<th>Action</th>
</tr>
<tr>
<td>1</td>
<td>SomeName</td>
<td>
Up
Down
</td>
</tr>
<tr>
<td>2</td>
<td>SomeName2</td>
<td>
Up
Down
</td>
</tr>
</table>
And I need to make functionality which allows to replacing table rows under <th># . When I put row with #2 on place #1 I want to keep proper orders of rows, 1,2 etc. I have row 2 on first place in my table but with #2, I need to change it.
It looks like this:
function moveChoiceTo(elem_choice, direction) {
var tr = elem_choice.parentNode.parentNode,
td = tr.parentNode;
if (direction === -1 && tr.previousElementSibling &&
!tr.previousElementSibling.id) {
td.insertBefore(tr, tr.previousElementSibling);
} else if (direction === 1 && tr.nextElementSibling) {
td.insertBefore(tr, tr.nextElementSibling.nextElementSibling)
}
}
But I still have no idea how to make my # unchanged. I want to use for it JQ but I've tried different solutions and none of them works.
I've tried
$(tr.firstElementChild.innerHTML).before($(tr.previousElementSibling.firstElementChild.innerHTML));
$(tr.firstElementChild.innerHTML).html(tr.previousElementSibling.firstElementChild.innerHTML);
$(tr.firstElementChild.innerHTML).replaceWith($(tr.previousElementSibling.firstElementChild.innerHTML));
And some others combination but i can't figured out what is wrong. Do I pass JS variable to JQ function in wrong way?
My table should looks like:
<table>
<tr id = 'first'>
<th>#</th>
<th>Name</th>
<th>Action</th>
</tr>
<tr>
<td>1</td>
<td>SomeName2</td>
<td>
Up
Down
</td>
</tr>
<tr>
<td>2</td>
<td>SomeName1</td>
<td>
Up
Down
</td>
</tr>
</table>
Name, action and others rows replaced places but #id is unchanged
EDIT.
Ok, I'm the stupidest man on the earth.
This is solution I was looking for:
$(tr.firstElementChild).html(tr.previousElementSibling.firstElementChild.innerHTML++);
when I go up, and
$(tr.firstElementChild).html(tr.nextElementSibling.firstElementChild.innerHTML--);
when I go down
Get second tr using $('tr').eq(1), then get all the children of tr and then use eq(1) to get second td.
const td1 = $('tr').eq(1).children().eq(1);
const td2 = $('tr').eq(2).children().eq(1);
const temp = td1.text();
td1.text(td2.text());
td2.text(temp);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table>
<tr id='first'>
<th>#</th>
<th>Name</th>
<th>Action</th>
</tr>
<tr>
<td>1</td>
<td>SomeName</td>
<td>
Up
Down
</td>
</tr>
<tr>
<td>2</td>
<td>SomeName2</td>
<td>
Up
Down
</td>
</tr>
</table>
Here's a simple solution using a delegate listener on the table element:
myTable.addEventListener('click', function({
target: t
}) {
if (t.tagName === 'BUTTON' && ['up', 'down'].includes(t.textContent.toLowerCase())) {
let row = t.closest('tr');
switch (t.textContent.toLowerCase()) {
case 'up':
let prevRow = row.previousElementSibling;
if (prevRow) {
row.parentElement.insertBefore(row, prevRow);
}
break;
case 'down':
let nextRow = row.nextElementSibling;
if (nextRow) {
row.parentElement.insertBefore(nextRow, row);
}
break;
}
}
})
<table id="myTable">
<thead>
<tr id="first">
<th>#</th>
<th>Name</th>
<th>Action</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td>SomeName1</td>
<td>
<button type="button">Up</button>
<button type="button">Down</button>
</td>
</tr>
<tr>
<td>2</td>
<td>SomeName2</td>
<td>
<button type="button">Up</button>
<button type="button">Down</button>
</td>
</tr>
<tr>
<td>3</td>
<td>SomeName3</td>
<td>
<button type="button">Up</button>
<button type="button">Down</button>
</td>
</tr>
<tr>
<td>4</td>
<td>SomeName4</td>
<td>
<button type="button">Up</button>
<button type="button">Down</button>
</td>
</tr>
<tr>
<td>5</td>
<td>SomeName5</td>
<td>
<button type="button">Up</button>
<button type="button">Down</button>
</td>
</tr>
<tr>
<td>6</td>
<td>SomeName6</td>
<td>
<button type="button">Up</button>
<button type="button">Down</button>
</td>
</tr>
</tbody>
</table>

How to show table rows between two days?

I have a table. I want to show only table rows which match between two days
<table id ="Table">
<thead>
<tr>
<th>Date</th>
<th>Name</th>
<th>Desc</th>
</tr>
</thead>
<tbody>
<tr>
<td> 20-06-2019</td>
<td> Payment </td>
<td >ajay </td>
<td>By cash</td>
</tr>
<tr>
<td>21-06-2019</td>
<td> Payment </td>
<td>ajay</td>
<td>By Cash</td>
</tr>
<tr>
<td>22-06-2019</td>
<td>Payment </td>
<td>ajay </td>
<td>Tran</td>
</tr>
<tr>
<td>23-06-2019</td>
<td> Payment </td>
<td class="table_account capitalize">ajay </td>
<td>By cash</td>
</tr>
</tbody>
</table>
I want to show rows between date 20-6-2019 to 22-6-2019.
20-6-2019 |Payment | Ajay | By cash|
21-6-2019 |Payment | Ajay |By cash |
22-6-2019 |Payment | Ajay |Tran |
As your data is getting from server , you should hidden table first by css . Then get data and send to javascript function as param I test with displayInterval as below
function displayInterval(from, to) {
$("#Table tbody tr td:first-child").each(function() {
var curDate = setJsDate($(this).html());
var froms =setJsDate(from);
var tos = setJsDate(to);
if(curDate >= froms && curDate <= tos) {
} else {
$(this).parent().hide();
}
});
$("#Table tbody").show();
}
function setJsDate(d) {
if(typeof d == "number" || typeof d == "undefined") return;
var pattern = d.split('-');
var dt = new Date(pattern[2]+"-"+pattern[1] + "-"+pattern[0]);
return dt.getTime();
}
displayInterval('20-06-2019','22-06-2019');
#Table tbody {
display : none;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table id ="Table">
<thead>
<tr>
<th>Date</th>
<th>Name</th>
<th>Desc</th>
</tr>
</thead>
<tbody>
<tr>
<td>20-06-2019</td>
<td> Payment </td>
<td >ajay </td>
<td>By cash</td>
</tr>
<tr>
<td>21-06-2019</td>
<td> Payment </td>
<td>ajay</td>
<td>By Cash</td>
</tr>
<tr>
<td>22-06-2019</td>
<td>Payment </td>
<td>ajay </td>
<td>Tran</td>
</tr>
<tr>
<td>23-06-2019</td>
<td> Payment </td>
<td class="table_account capitalize">ajay </td>
<td>By cash</td>
</tr>
</tbody>
</table>
<table id ="Table">
<thead>
<tr>
<th>Date</th>
<th>Name</th>
<th>Desc</th>
</tr>
</thead>
<tbody>
<tr>
<td> 20-06-2019</td>
<td> Payment </td>
<td >ajay </td>
<td>By cash</td>
</tr>
<tr>
<td>21-06-2019</td>
<td> Payment </td>
<td>ajay</td>
<td>By Cash</td>
</tr>
<tr>
<td>22-06-2019</td>
<td>Payment </td>
<td>ajay </td>
<td>Tran</td>
</tr>
</tbody>
</table>

How to get total sum in multiple tables

I have a multiple table and I want to get the total per table. Please see the demo in fiddle.
var total = 0;
$("table").each(function(i){
total += +$('.a', this).text() || 0;
console.log( 'total: '+total );
$("#subtotal", this).text( total );
//console.log( '-'+$('.a', this).text() );
});
https://jsfiddle.net/juandela/6r1g30dx/2/
You need to move var total=0 inside the table loop so it resets for each table
Then you need to loop over each cell to get individual cell's text.
The problem with getting all $('.a', this).text() is it concatenates all elements text into one string which is why you see numbers like "1357" as total in first table
Finally you can't repeat ID's in page so change subtotal to a class
$("table").each(function(i) {
var total = 0;
$('.a', this).each(function() {
total += +$(this).text() || 0;
});
$(".subtotal", this).text(total);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table>
<tr>
<td class="a">1</td>
<td>2</td>
</tr>
<tr>
<td class="a">3</td>
<td>4</td>
</tr>
<tr>
<td class="a">5</td>
<td>6</td>
</tr>
<tr>
<td class="a">7</td>
<td>8</td>
</tr>
<tr>
<td class="subtotal"></td>
</tr>
</table>
<hr>
<table>
<tr>
<td class="a">1</td>
<td>2</td>
</tr>
<tr>
<td class="a">3</td>
<td>4</td>
</tr>
<tr>
<td class="a">5</td>
<td>6</td>
</tr>
<tr>
<td class="a">7</td>
<td>8</td>
</tr>
<tr>
<td class="a">9</td>
<td>10</td>
</tr>
<tr>
<td class="a">11</td>
<td>12</td>
</tr>
<tr>
<td class="subtotal"></td>
</tr>
</table>

Sort Table Rows according to table data

For example, I have a code:
<table>
<tr>
<th>name</td>
<th>price</td>
</tr>
<tr>
<td>a</td>
<td class="sort">5</td>
</tr>
<tr>
<td>b</td>
<td class="sort">3</td>
</tr>
<tr>
<td>c</td>
<td class="sort">8</td>
</tr>
<tr>
<td>c</td>
<td class="sort"></td>
</tr>
<tr>
<td>h</td>
<td class="sort">2</td>
</tr>
<tr>
<td>p</td>
<td class="sort">6</td>
</tr>
<tr>
<td>b</td>
<td class="sort">20</td>
</tr>
<tr>
<td>b</td>
<td class="sort"></td>
</tr>
</table>
I want this to be sorted like this:
<table>
<tr>
<th>name</td>
<th>price</td>
</tr>
<tr>
<td>h</td>
<td class="sort">2</td>
</tr>
<tr>
<td>b</td>
<td class="sort">3</td>
</tr>
<tr>
<td>a</td>
<td class="sort">5</td>
</tr>
<tr>
<td>p</td>
<td class="sort">6</td>
</tr>
<tr>
<td>c</td>
<td class="sort">8</td>
</tr>
<tr>
<td>b</td>
<td class="sort">20</td>
</tr>
<tr>
<td>c</td>
<td class="sort"></td>
</tr>
<tr>
<td>b</td>
<td class="sort"></td>
</tr>
</table>
I used this code:
function sortNum(a, b) {
return 1 * $(a).find('.sort').text() < 1 * $(b).find('.price').text() ? 0 : 1;
}
function sortTheTable(){
$(function() {
var elems = $.makeArray($('tr:has(.price)').remove())
elems.sort(sortNum)
$('table#information').append($(elems));
});
}
this works but, the problem is, the output is like this:
<table>
<tr>
<th>name</td>
<th>price</td>
</tr>
<tr>
<td>c</td>
<td class="sort"></td>
</tr>
<tr>
<td>b</td>
<td class="sort"></td>
</tr>
<tr>
<td>h</td>
<td class="sort">2</td>
</tr>
<tr>
<td>b</td>
<td class="sort">3</td>
</tr>
<tr>
<td>a</td>
<td class="sort">5</td>
</tr>
<tr>
<td>p</td>
<td class="sort">6</td>
</tr>
<tr>
<td>c</td>
<td class="sort">8</td>
</tr>
<tr>
<td>b</td>
<td class="sort">20</td>
</tr>
</table>
The empty one goes to top. I want the empty ones in the bottom.
Thanks
Instead of
return 1 * $(a).find('.sort').text() < 1 * $(b).find('.sort').text() ? 1 : 0;
insert
return 1 * $(a).find('.sort').text() < 1 * $(b).find('.price').text() ? 0 : 1;
http://jsfiddle.net/E56j8/
You have number of plugins to sort it why are you reinventing the wheel.
Here is one such plugin
Link
<script type="text/javascript" src="/path/to/jquery-latest.js"></script>
<script type="text/javascript" src="/path/to/jquery.tablesorter.js"></script>
$("#myTable").tablesorter();
Have a look at Sorting - we're doing it wrong. A simple jQuery plugin for sorting stuff is available here.
some notes on your code:
// you're binding a document ready event within a function call?
// looks the wrong way 'round, to me
function sortTheTable(){
$(function() {
// 1) you probably want to use .detach() over .remove()
// 2) "tr:has(.price)" will match ALL table rows
// containing an element with the class .price
// even if they're children of different <table>s!
// 3) $('.selector') is already "an array", at least it's sortable right away.
// there's no need for $.makeArray() here
var elems = $.makeArray($('tr:has(.price)').remove())
elems.sort(sortNum)
// "#information" is a sufficient (and more efficient) selector,
$('table#information').append($(elems));
});
}

Categories

Resources