Replace elements value of table - javascript

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>

Related

Transfer variables between tables

On my html I have multiple tables, which are for different valuations. The results of those valuations are supposed to be in another table. The text of valuation_all in the tables.taglist should be transferred into another table. I'm really lost here. Newby with this topic so I'll appreciate every help!
Table for summary results
<table id="results" class="summary">
<th>Test</th>
<th>result</th>
<tr>
<td>E-01</td>
<td>text</td>
</tr>
<tr>
<td>E-02</td>
<td>text</td>
</tr>
</table>
Tables of valuation
<p>
<table id="results1" class="taglist">
<th>Name</th>
<th>result</th>
<tr>
<td class="valuation">FAIL</td>
<td rowspan=2 class="valuation_all">FAIL</td>
</tr>
<tr>
<td class="valuation">PASS</td>
</tr>
</table>
</p>
<p>
<table id="results2" class="taglist">
<th>Name</th>
<th>result</th>
<tr>
<td class="valuation">x</td>
<td class="valuation_all" rowspan=2>OPEN</td>
</tr>
<tr>
<td class="valuation">x</td>
</tr>
</table>
</p>
Assuming your results list tables are ordered the same way you ordered rows in your global results table, you can perform a forEach on all .valuation_all, and then mirror each text on the global results table:
const resTables = document.querySelectorAll('.valuation_all')
const results = document.querySelectorAll('#results tr > td + td')
resTables.forEach( function(el, i) {
results[i].textContent = el.textContent
})
<table id="results" class="summary">
<tr>
<th>Test</th><th>result</th>
</tr>
<tr>
<td>E-01</td><td>text</td>
</tr>
<tr>
<td>E-02</td><td>text</td>
</tr>
</table>
<hr>
<table id="results1" class="taglist">
<tr>
<th>Name</th><th>result</th>
</tr>
<tr>
<td class="valuation">FAIL</td><td rowspan="2" class="valuation_all">FAIL</td>
</tr>
<tr>
<td class="valuation">PASS</td>
</tr>
</table>
<table id="results2" class="taglist">
<tr>
<th>Name</th><th>result</th>
</tr>
<tr>
<td class="valuation">x</td><td class="valuation_all" rowspan="2">OPEN</td>
</tr>
<tr>
<td class="valuation">x</td>
</tr>
</table>
Please consider using data attributes for better matching.
https://developer.mozilla.org/en-US/docs/Learn/HTML/Howto/Use_data_attributes

Problem with Expanding and shrinking Table on load

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>

Get a specific row from specific table with JavaScript?

Say my dynamic HTML looks something like this:
<table id="DanishCompanies">
<tr><th>Name</th><th>Employees</th><th>Founded</th></tr>
<tr id="19"><td>Company A</td><td>80</td><td>1980</td></tr>
<tr id="17"><td>Company B</td><td>12</td><td>1910</td></tr>
<tr id="26"><td>Company C</td><td>5000</td><td>2015</td></tr>
</table>
<table id="SwedishCompanies">
<tr><th>Name</th><th>Employees</th><th>Founded</th></tr>
<tr id="10"><td>Company D</td><td>500</td><td>1950</td></tr>
<tr id="12"><td>Company E</td><td>900</td><td>1990</td></tr>
<tr id="17"><td>Company F</td><td>90</td><td>2010</td></tr>
</table>
<table id="NorwegianCompanies">
<tr><th>Name</th><th>Employees</th><th>Founded</th></tr>
<tr id="17"><td>Company G</td><td>105</td><td>1970</td></tr>
<tr id="18"><td>Company H</td><td>100</td><td>1980</td></tr>
<tr id="19"><td>Company I</td><td>45</td><td>2000</td></tr>
</table>
Each tr has an ID, but ID only relatively unique to the table, as other tables might have the ID, and the number of rows might vary.
How would I obtain the founding year (column 2) of a Swedish company with an id of 17?
I would imagine you would do it like this but I fail to find the correct code.
var table = document.getElementById("SwedishCompanies");
var row_index = ??? //should return 2
return table[row_index].cells[2].innerHTML;
I can't use getElementById just to get id "17", because I would risk getting Danish or Norwegian's company because the order of these tables is random.
you're just not using the right selector,
#DanishCompanies tr[id="17"]
will get you the tr with id 17 that's a child of DanishCompanies :
const row = document.querySelector('#DanishCompanies tr[id="17"]');
const year = row.cells[2].innerHTML;
console.log(year);
<table id="DanishCompanies">
<tr>
<th>Name</th>
<th>Employees</th>
<th>Founded</th>
</tr>
<tr id="19">
<td>Company A</td>
<td>80</td>
<td>1980</td>
</tr>
<tr id="17">
<td>Company B</td>
<td>12</td>
<td>1910</td>
</tr>
<tr id="26">
<td>Company C</td>
<td>5000</td>
<td>2015</td>
</tr>
</table>
<table id="SwedishCompanies">
<tr>
<th>Name</th>
<th>Employees</th>
<th>Founded</th>
</tr>
<tr id="10">
<td>Company D</td>
<td>500</td>
<td>1950</td>
</tr>
<tr id="12">
<td>Company E</td>
<td>900</td>
<td>1990</td>
</tr>
<tr id="17">
<td>Company F</td>
<td>90</td>
<td>2010</td>
</tr>
</table>
<table id="NorwegianCompanies">
<tr>
<th>Name</th>
<th>Employees</th>
<th>Founded</th>
</tr>
<tr id="17">
<td>Company G</td>
<td>105</td>
<td>1970</td>
</tr>
<tr id="18">
<td>Company H</td>
<td>100</td>
<td>1980</td>
</tr>
<tr id="19">
<td>Company I</td>
<td>45</td>
<td>2000</td>
</tr>
</table>
this way (id with number values complicates the css select syntax)
function getTDval( tableId, rowId, colNum)
{
return document
.querySelector(`table#${tableId} tr[id="${rowId}"]`)
.cells[colNum].textContent
}
console.log( getTDval('SwedishCompanies','17',2) )
<table id="DanishCompanies">
<tr><th>Name</th><th>Employees</th><th>Founded</th></tr>
<tr id="19"><td>Company A</td><td>80</td><td>1980</td></tr>
<tr id="17"><td>Company B</td><td>12</td><td>1910</td></tr>
<tr id="26"><td>Company C</td><td>5000</td><td>2015</td></tr>
</table>
<table id="SwedishCompanies">
<tr><th>Name</th><th>Employees</th><th>Founded</th></tr>
<tr id="10"><td>Company D</td><td>500</td><td>1950</td></tr>
<tr id="12"><td>Company E</td><td>900</td><td>1990</td></tr>
<tr id="17"><td>Company F</td><td>90</td><td>2010</td></tr>
</table>
<table id="NorwegianCompanies">
<tr><th>Name</th><th>Employees</th><th>Founded</th></tr>
<tr id="17"><td>Company G</td><td>105</td><td>1970</td></tr>
<tr id="18"><td>Company H</td><td>100</td><td>1980</td></tr>
<tr id="19"><td>Company I</td><td>45</td><td>2000</td></tr>
</table>
It is invalid HTML to reuse the same id value within a page. You might use private data-... attributes for that.
Apart from that, the following line gets the human readable text of the third child node (third column in this case), which is the year (as a string).
document.querySelector('#DanishCompanies tr[id="17"]')
.children[2].innerText;
If you can't rely on getElmentById that means that you are doing something wrong, an id should be unique in the whole html. I suggest a new naming technique, you can concatenate the parent table id with the current row id. Example:
<table id="NorwegianCompanies">
<tr><th>Name</th><th>Employees</th><th>Founded</th></tr>
<tr id="NorwegianCompanies17"><td>Company G</td><td>105</td><td>1970</td></tr>
<tr id="NorwegianCompanies18"><td>Company H</td><td>100</td><td>1980</td></tr>
<tr id="NorwegianCompanies19"><td>Company I</td><td>45</td><td>2000</td></tr>
</table>
In that way you can simply call
const row = document.getElementById(rowId)

How I can find all the elements in DOM having z-index value

I've a table in my code which contains lots of rows and every row contains some td's, I want to find all the td's having z-index value.
For Example -
<table>
<thead>
<tr>
<td>name</td>
</tr>
</thead>
<tbody>
<tr>
<td style="z-index: 10">jhon</td>
</tr>
<tr>
<td>
doy
</td>
</tr>
<tr>
<td style="z-index: 20">jam</td>
</tr>
</tbody>
</table>
Can anybody help me to find all the td's having z-index value without using any loop?
You can find all the td's, then filter out those which don't have any z-index set. I'm fairly sure there's no way to do the initial select on a more specific level than this.
const test = [
...document.getElementsByTagName("td")
].filter(x => x.style.zIndex !== "")
test.forEach(x => x.style.color = "#"+((1<<24)*Math.random()|0).toString(16))
console.dir(test)
<table>
<thead>
<tr>
<td>name</td>
</tr>
</thead>
<tbody>
<tr>
<td style="z-index: 10">jhon</td>
</tr>
<tr>
<td>
doy
</td>
</tr>
<tr>
<td style="z-index: 20">jam</td>
</tr>
</tbody>
</table>
So this is give you the same result but with jquery and this is why i added a
position:relative
For z-index to work correctly, every element that has a z-index property must also have any position set ( e.g.position:relative )
$(document).ready(function() {
$("td").each(function() {
// td Element
const $this = $(this);
// your logic condition
if ($this.css("z-index") !== "auto") {
$this.css("color", "red");
}
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table>
<thead>
<tr>
<td>name</td>
</tr>
</thead>
<tbody>
<tr>
<td style=" position: relative; z-index: 10">jhon</td>
</tr>
<tr>
<td>
doy
</td>
</tr>
<tr>
<td style=" position: relative; z-index: 20">jam</td>
</tr>
</tbody>
</table>

How to move a row that has data-search attributes to another table?

I am trying to move a selected row in my DataTable to another DataTable. I have this almost working but the problem is with the cells that have data-search attributes on them. That data just gets placed into my other table as [object Object]. I've tried finding an example on how to handle this case in the documentation but I'm not having any luck. Here is what I have..
https://jsfiddle.net/dmcgrew/x85o0mgL/5/
HTML..
<table id="selected_items">
<thead>
<tr>
<th>Item</th>
<th>Description</th>
<th>Crest Allowed</th>
<th> </th>
</tr>
</thead>
<tbody>
</tbody>
</table>
<table id="select_items">
<thead>
<tr>
<th>Item</th>
<th>Description</th>
<th>Crest Allowed</th>
<th> </th>
</tr>
</thead>
<tbody>
<tr id="1">
<td data-search="test">1</td>
<td>Testing Bowl</td>
<td data-search="nocrest">NO</td>
<td><button class="button select">Select</button></td>
</tr>
<tr>
<td data-search="test">32</td>
<td>Cup Test</td>
<td data-search="nocrest">NO</td>
<td><button class="button select">Select</button></td>
</tr>
<tr>
<td data-search="pristine">3335</td>
<td>Bowl Test</td>
<td data-search="nocrest">NO</td>
<td><button class="button select">Select</button></td>
</tr>
<tr>
<td data-search="pristine">120</td>
<td>Plate Test</td>
<td data-search="yescrest">YES</td>
<td><button class="button select">Select</button></td>
</tr>
<tr>
<td data-search="test">1000</td>
<td>Mug Test</td>
<td data-search="yescrest">YES</td>
<td><button class="button select">Select</button></td>
</tr>
<tr>
<td data-search="pristine">65</td>
<td>Ramekin Test</td>
<td data-search="yescrest">YES</td>
<td><button class="button select">Select</button></td>
</tr>
</tbody>
</table>
JS...
var select_items = $('.select_items').dataTable();
var selected_items = $('#selected_items').DataTable();
$('.select_items').on("click", "button.select", function(){
var selectedRow = select_items.api().row( $(this).parents("tr") ).data();
selected_items.row.add(selectedRow).draw(true);
});
Your basic problem is the data.
When a td has a data attribute (data-search), it is included in the data object so your data array looks like this:
[{display:"1", #data-search:"test"}, "Testing Bowl", {display: "NO", #data-search: "nocrest"}, "Select"] so first and third items in the array are, in fact objects, hence [object, object]
so the quickest (not the best in my mind) is to alter the data before you add it.
select_items.on("click", "button.select", function(){
var selectedRow = select_items.api().row( $(this).parents("tr") ).data();
console.log(selectedRow);
selectedRow[0] = selectedRow[0].display;
selectedRow[2] = selectedRow[2].display;
selected_items.row.add(selectedRow).draw(true);
});
https://jsfiddle.net/x85o0mgL/12/

Categories

Resources