I'm building an e-mail constructor and when the user saves the template I just send the HTML to the server. But I need to remove the drap & drop element to send it to the server.
I'm not very good with DOM manipulation so I don't know where to start from.
This is my HTML:
<table>
<tbody>
<tr>
<th>
<div class="components-drop-area">
<p>aa</p>
<p>bb</p>
</div>
</th>
</tr>
<tr>
<th>
<div class="components-drop-area">
<p>cc</p>
<p>dd</p>
</div>
</th>
</tr>
</tbody>
</table>
I need to remove all the .components-drop-area divs. Something like that:
<table>
<tbody>
<tr>
<th>
<p>aa</p>
<p>bb</p>
</th>
</tr>
<tr>
<th>
<p>cc</p>
<p>dd</p>
</th>
</tr>
</tbody>
</table>
I stopped my code here:
var table = document.querySelector('table').cloneNode(true)
let dropAreas = table.querySelectorAll('.components-drop-area')
console.log(table, dropAreas)
How can I loop and remove desired elements while retaining their content?
One way would simply be to replace the parentNode's innerHTMLs with the .components-drop-area innerHTMLs:
let dropAreas = document.querySelectorAll('.components-drop-area');
for (let i = 0; i < dropAreas.length; i++) {
dropAreas[i].parentNode.innerHTML = dropAreas[i].innerHTML;
}
// The <div> contents have now been extracted, and the <div> elements removed
console.log(document.querySelector('table').innerHTML);
<table>
<tbody>
<tr>
<th>
<div class="components-drop-area">
<p>aa</p>
<p>bb</p>
</div>
</th>
</tr>
<tr>
<th>
<div class="components-drop-area">
<p>cc</p>
<p>dd</p>
</div>
</th>
</tr>
</tbody>
</table>
Here's an adaption of James's vanilla JS implementation that should work
for (const node of document.querySelectorAll("table .components-drop-area")) {
const parent = node.parentNode;
while (node.children.length>0) {
let child = node.children[0];
node.removeChild(child);
parent.insertBefore(child, node);
}
parent.removeChild(node);
}
Looping over the elements is tricky since we're modifying the collection during the iteration
for (const node of document.querySelectorAll("table .components-drop-area")) {
const parent = node.parentNode;
while (node.children.length>0) {
let child = node.children[0];
node.removeChild(child);
parent.insertBefore(child, node);
}
parent.removeChild(node);
}
// The <div> contents have now been extracted, and the <div> elements removed
console.log(document.querySelector('table').innerHTML);
<table>
<tbody>
<tr>
<th>
<div class="components-drop-area">
<p>aa</p>
<p>bb</p>
</div>
</th>
</tr>
<tr>
<th>
<div class="components-drop-area">
<p>cc</p>
<p>dd</p>
</div>
</th>
</tr>
</tbody>
</table>
If you want to use vanilla DOM operations, you would have to take each child from selected div elements and insert them into that node's parent element using the selected div itself as a reference before removing it. Every DOM node has a reference to its parent and its children, so you can do everything relative to each selected node like so:
for (const node of document.querySelectorAll("table .components-drop-area")) {
const parent = node.parentNode;
const children = Array.from(node.children);
for (const child of children) {
node.removeChild(child);
parent.insertBefore(child, node);
}
parent.removeChild(node);
}
An elegant solution using jQuery would be:
$('.components-drop-area').contents().unwrap();
console.log(document.querySelector('table').innerHTML);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table>
<tbody>
<tr>
<th>
<div class="components-drop-area">
<p>aa</p>
<p>bb</p>
</div>
</th>
</tr>
<tr>
<th>
<div class="components-drop-area">
<p>cc</p>
<p>dd</p>
</div>
</th>
</tr>
</tbody>
</table>
Notes:
contents()
unwrap()
Related
I have a html table with multiple rows and columns. I want to pull all the values by column id and compare with some matching string. If matches i want to enable a button on the page.
Could you please let me know how to refer the column by id in $(document).ready function.
Here is the table
<table id="data" class="table">
<thead>
<tr class="DataT1">
<th>Id</th>
<th>Name</th>
<th>Place</th>
</tr>
</thead>
<th:block th:each="it : ${data}">
<tr>
<td th:text="${it.id}">id</td>
<td th:text="${it.name}">name</td>
<td th:text="${it.place}">place</td>
</tr>
</th:block>
</table>
Button:
style="visibility:hidden">Submit
$(document).ready(function(){
//here i want to pull the place column and verify if one of the
places matches my input string enable submit button
$("#submitbutton").css("visibility", "visible");
}
}
This function will take all information inside you td and search for the string you looking for :
But i cannot get the point that you search for a particular string instead of searching for an object.
const addresses = [...document.querySelectorAll(".address")];
const serchFromList = (arr, str) => {
return arr.map(el =>
el = el.innerHTML
).filter(el => el === str)
}
console.log(serchFromList(addresses, "NY"))
/* in case you want a boolean you can use some*/
const isAddressExist = (arr, str) => {
return arr.map(el =>
el = el.innerHTML
).some(el => el === str)
}
console.log(isAddressExist(addresses, "NY"))
<table id="data" class="table">
<thead>
<tr class="DataT1">
<th>Id</th>
<th>Name</th>
<th>Place</th>
</tr>
</thead>
<th>
<tr>
<td>4545</td>
<td>5454</td>
<td>65687</td>
</tr>
<tr>
<td>aziz</td>
<td>david</td>
<td>paul</td>
</tr>
<tr>
<td class='address'>NY</td>
<td class='address'>MTL</td>
<td class='address'>BC</td>
</tr>
</th>
</table>
Should be pretty doable with XPath if you don't want to add extra attributes to Place cell. Just find out the position of Place column and get the text from the same position of <td>.
// Get the table node first
let node = document.getElementById('data')
// Find out position of `Place` column
let nth = document.evaluate('count(//th[text()="Place"]/preceding-sibling::*)+1', node).numberValue
// Get all the place cell by the position
let placeCells = document.evaluate(`//td[position()=${nth}]`, node)
// Get all the place names
let places = [],
placeNode = placeCells.iterateNext()
while (placeNode) {
places.push(placeNode.textContent)
placeNode = placeCells.iterateNext()
}
console.log(places)
// ['NYC', 'SF', 'LA']
<table id="data" class="table">
<thead>
<tr class="DataT1">
<th>Id</th>
<th>Name</th>
<th>Place</th>
</tr>
</thead>
<tbody>
<tr>
<td>0001</td>
<td>Mary</td>
<td>NYC</td>
</tr>
<tr>
<td>0002</td>
<td>John</td>
<td>SF</td>
</tr>
<tr>
<td>0003</td>
<td>Bob</td>
<td>LA</td>
</tr>
</tbody>
</table>
I'm using html5 and jquery to set up a dynamic table, until then I can add the elements to the table without problems, but I can not retrieve the value of its columns. so I have the following questions:
How can I recover the table data by clicking the ROW?
Should I always use the data-name, id for example as in the first
line ?
$(document).on("change", "#TabClientesAdicionados", function(e) {
alert('?');
});
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet" />
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<hr>
<table id="TabClientesAdicionados" class="table table-hover">
<thead>
<tr>
<th> ID </th>
<th> Name </th>
<th> Actions </th>
</tr>
</thead>
<tbody>
<tr>
<td data-id="Bruno">1</td>
<td data-nome="Bruno">Bruno</td>
<td>Details</td>
</tr>
<tr>
<td>2</td>
<td>Josep</td>
<td> Details </td>
</tr>
</tbody>
</table>
How can I recover the table data by clicking the ROW?
You can bind the click event to your TR elements and get the information.
Should I always use the data-name, id for example as in the first line?
Yes, because you don't want the parsed HTML to manipulate data. The data attributes are a better approach to keep related data (no HTML) to DOM elements.
Look at this code snippet
This approach binds the click event to TR elements
$('#TabClientesAdicionados tbody tr').click(function() {
var data = { name: '', id: '' };
$(this).children('td').each(function() {
var name = $(this).data('nome');
if (name) {
data.name = name;
}
var id = $(this).data('id');
if (id) {
data.id = id;
}
});
console.log(data);
});
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet" />
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<hr>
<table id="TabClientesAdicionados" class="table table-hover">
<thead>
<tr>
<th> ID </th>
<th> Name </th>
<th> Actions </th>
</tr>
</thead>
<tbody>
<tr>
<td data-id="Bruno_1">1</td>
<td data-nome="Bruno">Bruno</td>
<td>Details</td>
</tr>
<tr>
<td>2</td>
<td>Josep</td>
<td> Details </td>
</tr>
</tbody>
</table>
I would do as the following snippet.
You need to bind the event to the row tr ant then get each of its children.
By adding a data attribute you could set a column name. This could also help if you eventually needed to extract the value of an specific cell.
Incidentally you could also add a second data attribute named like data-value or something similar- This in case you are worried that your parsed html content might cause you trouble with the values.
$(document).ready(function() {
$("#mytable").on('click', 'tr', onCellClick);
//Bind the event to the table row
function onCellClick() {
let row = $(this); //get the jquery Object for the row
let rowValues = {}; //An empty object to hold your data
let temp;
//extract the value of every cell in the row
//Doing it this way gives you flexibility on the amount of colums you have
row.find('td').each(function(item) {
temp = $(this);
rowValues[temp.data('column')] = temp.text();
//this could be changed to
//rowValues[temp.data('column')] = temp.data('value);
//if you desire to use a separate data-value property
});
console.log(rowValues);
}
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<table style="width:100%" id="mytable">
<tr>
<th>Firstname</th>
<th>Lastname</th>
<th>Age</th>
</tr>
<tr>
<td data-column="name" data-value="Jill">Jill</td> <!-Adding value property-->
<td data-column="lastname">Smith</td>
<td data-column="age">50</td>
</tr>
<tr>
<td data-column="name">Eve</td>
<td data-column="lastname">Jackson</td>
<td data-column="age">94</td>
</tr>
</table>
I have a bootstrap table in my react project. I want to get the index of row which I click on. I want to do something like this onclick = {this.handleClick} and in handleClick function I want to get the index of row. Is it possible to do it. Most of the solutions available shows everything using jquery and I don't want to use Jquery. I want to do it using just javascript only. This is my table
<Table className='flags-table' responsive hover>
<thead>
<tr>
<th> </th>
<th> Time In </th>
<th> Time Out </th>
<th> Type </th>
<th> Category </th>
</tr>
</thead>
<tbody>
{
FLAGS_LIST.map((x,i)=> (
<tr key={i}>
<td> <div className='red-box'></div> </td>
<td> {x.time_in} </td>
<td> {x.time_out} </td>
<td> {x.type} </td>
<td> {x.category} </td>
</tr>
))
}
</tbody>
</Table>
You can use code like this:
onclick = {this.handleClick.bind(this, i)};
and handleClick should declare like this:
var handleClick = function(i) {
console.log("key of row", i)
...
};
I'm trying to alert the table(parent) class on click using the child id <th id="first">.
alert($(this).parent('tr').attr('class')); using this i have got the class of the <tr>.
But i want to get the class of the table when i use alert($(this).parent('table').attr('class')); it showing alert says undefined can someone help me how can the parent class using the child id
<table class="table table-bordered">
<thead>
<tr class="sample">
<th id="first">Firstname</th>
<th id="last">Lastname</th>
<th id="user">Username</th>
</tr>
</thead>
<tbody>
<tr>
<td>arun </td>
<td>kumaresh</td>
<td>arun kumaresh</td>
</tr>
</tbody>
</table>
</div>
<script>
$(document).ready(function(){
$("#first").click(function(){
alert($(this).parent('tr').attr('class'));
});
});
</script>
Use .closest(TARGET_SELECTOR), For each element in the set, get the first element that matches the selector by testing the element itself and traversing up through its ancestors in the DOM tree.
As .parent(SELECTOR), Get the parent of each element in the current set of matched elements, optionally filtered by a selector. (the parent() method traverses to the immediate parent)
$(document).ready(function() {
$("#first").click(function() {
alert($(this).closest('table').attr('class'));
});
$("#last").click(function() {
alert($(this).closest('thead').attr('class'));
});
$(".user").click(function() {
alert($(this).closest('table').attr('class'));
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
<table class="table table-bordered">
<thead class='ANY_CLASS'>
<tr class="sample">
<th id="first">Firstname</th>
<th id="last">Lastname</th>
<th class="user">Username</th>
</tr>
</thead>
<tbody>
<tr>
<td>arun</td>
<td>kumaresh</td>
<td>arun kumaresh</td>
</tr>
</tbody>
</table>
simply use
alert($(this).closest('table').attr('class'));
refer closest here
https://api.jquery.com/closest/
I have a table structured as below. As I cannot change anything about how the HTML is created but I can add some lines I want to solve this via JavaScript.
What I want is that:
(1) the table gets an additional <thead> element
(2) the <tr> element with class firstline becomes a child of <thead>
<table>
<tbody>
<tr class= firstline >
<th> 1st column </th>
<th> 2nd column </th>
</tr>
<tr class= content >
<th> foo </th>
<th> bat </th>
</tr>
</tbody>
</table>
So far, I manage to delete the <tr class= firstline > element and I manage to add a <thead> element to the table. But I have no clue how to insert the <tr class= firstline > into the <thead> ???
var firstLines = document.getElementsByClassName("firstline");
for (var i=0; i<firstLines.length; i++) {
var FLparent = firstLines[i].parentNode.parentNode;
var tbody = document.createElement("thead") ;
FLparent.insertBefore(tbody, FLparent.firstChild);
FLparent.firstChild.appendChild(firstLines[i]);
firstLines[i].parentNode.removeChild(firstLines[i]);
}
It could be as simple as:
var
table = document.querySelector('table'),
tHead = table.insertBefore(document.createElement('thead'), table.firstChild);
tHead.appendChild(
table.querySelector('tr.firstline')
);
http://jsbin.com/ruza/3/