I want to store some information in DOM elements (rows of table). I think I can do it using jQuery's data() function. I wrote some test code and found out that I can't get the stored data from elements using jQuery selectors. Is it possible? Maybe I'm doing something wrong?
Here is the simple code:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>JQuery data() test</title>
<script src="https://code.jquery.com/jquery-latest.js" type="text/javascript"></script>
</head>
<body>
<table id="myTable">
<tbody>
<tr id="rowPrototype" style="display:none;">
<td class="td1"></td>
<td class="td2"></td>
</tr>
</tbody>
</table>
<script>
var table = $("#myTable");
for (var i = 0; i < 5; i++) {
var newRow = $("#rowPrototype").clone();
newRow.removeAttr("style");
newRow.removeAttr("id");
$.data(newRow, "number", i);
console.log("Data added to row: " + $.data(newRow, "number"));
var tds = newRow.find("td");
tds.text("test");
table.append(newRow);
}
var trs = table.find("tr");
trs.each(function () {
var tr = $(this).text();
var data = $.data(tr, "number");
console.log("number: " + data);
});
</script>
</body>
</html>
I expect the following output:
number: undefined (row prototype)
number: 0
number: 1
number: 2
number: 3
number: 4
But actual is:
number: undefined
number: undefined
number: undefined
number: undefined
number: undefined
number: undefined
So what's wrong with this code?
UPD
You can test it here: https://jsfiddle.net/rfrz332o/3/
$.data() expects an actual DOM element as the first argument, not a jQuery object. You can $(selector).data() with jQuery objects. I'd suggest you change this:
$.data(newRow, "number", i);
console.log("Data added to row: " + $.data(newRow, "number"));
to this:
newRow.data("number", i);
console.log("Data added to row: " + newRow.data("number"));
And, then change this:
var trs = table.find("tr");
trs.each(function () {
var tr = $(this).text();
var data = $.data(tr, "number");
console.log("number: " + data);
});
to this:
table.find("tr").each(function () {
console.log("number: " + $(this).data("number"));
});
You messed with data method. You weren't applying data to dynamic created row. To see result, please check your console.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>JQuery data() test</title>
<script src="https://code.jquery.com/jquery-latest.js" type="text/javascript"></script>
</head>
<body>
<table id="myTable">
<tbody>
<tr id="rowPrototype" style="display:none;">
<td class="td1"></td>
<td class="td2"></td>
</tr>
</tbody>
</table>
<script>
var table = $("#myTable");
for (var i = 0; i < 5; i++) {
var newRow = $("#rowPrototype").clone();
newRow.removeAttr("style");
newRow.removeAttr("id");
newRow.data("number", i);
console.log("Data added to row: " + newRow.data("number"));
var tds = newRow.find("td");
tds.text("test");
table.append(newRow);
}
var trs = table.find("tr");
trs.each(function () {
var tr = $(this).text();
var data = $(this).data("number")
console.log("number: " + data);
});
</script>
</body>
</html>
$.data() expects DOM element, not jQuery object. Add [i] or use .get(i) at $.data(newRow[i], "number", i); and all js that follows where $.data() is used to reference DOM element.
There is also an issue with the for loop. If there is actually only one tr element and two td elements within #myTable, when i reaches 2 , if the selector included i the result would be undefined, as the maximum index of td elements would still be 1 within the cloned table ; whether $.data() or .data() is used. Similarly for the one tr element within #myTable; when i reaches 1
jQuery.data( element, key, value )
element
Type: Element
The DOM element to associate with the data.
Related
I'm trying to get the data from a datatable. I know that i can use datatable.data() but my cells have html data inside so I get something like this:
0:
CIF: "<span class='text-success font-weight-bold'>B81692097</span>"
CODIGO CURSO: "<div class='d-flex justify-content-center'><i data-toggle='tooltip' data-type='CODIGO CURSO' data-placement='top' title='Rellenar celda' class='empty-cell editable-data material-icons text-info'>keyboard</i></div>"
CODIGO USUARIO: "12345678-A"
DT_RowId: "row_1"
EDITORIAL: "CONZEPTO"
FACTURABLE: "<i class='material-icons text-success'>check_circle</i>"
FECHA ACTIVACION: 43831
HORAS: 1
LICENCIA: "-"
NOMBRE CENTRO: "<span class='text-success font-weight-bold'>ACADEMIA LIDER SYSTEM S.L.</span>"
NOMBRE CURSO: "<div class='d-flex justify-content-center'><span data-type='NOMBRE CURSO' class='editable-data text-info font-weight-bold'>Marketing y cosas</div>"
NOMBRE USUARIO: "Jose Perez Perez"
PERFIL: "-"
PRECIO: 1
REFERENCIA: "<div class='d-flex justify-content-center'><i data-toggle='tooltip' data-type='REFERENCIA' data-placement='top' title='Rellenar celda' class='empty-cell editable-data material-icons text-info'>keyboard</i></div>"
URL: "<span class='text-success font-weight-bold'>campusonline.lidersystem.com</span>"
VALIDADO: "↵ <span class='d-none orderable-value'>2</span>↵ <i data-toggle='tooltip
And, for example, from CIF I want to get B81692097 instead of <span class='text-success font-weight-bold'>B81692097</span>
I know that I could make a function to get the specific data from every cell but I wonder if there is an easier way to do this, I have been searching in the docs but I couldnt find anything.
Is there any way to get this with the tools that datatable offers?
Thank you guys
Depending on what specific data you need, here are some examples in a stand-alone demo you can run for yourself.
This includes an example showing the removal of HTML tags from cell data.
The demo table:
To see the results, uncomment the relevant console.log() statement(s). The browser console (F12) will show the output:
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Iterate Cells</title>
<script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
<script src="https://cdn.datatables.net/1.10.20/js/jquery.dataTables.min.js"></script>
<link rel="stylesheet" type="text/css" href="https://cdn.datatables.net/1.10.20/css/jquery.dataTables.min.css">
<link rel="stylesheet" type="text/css" href="https://datatables.net/media/css/site-examples.css">
</head>
<body>
<div style="margin: 20px;">
<table id="demo" class="display dataTable cell-border" style="width:100%">
<thead>
<tr><th>Column One</th><th>Column Two</th></tr>
</thead>
<tbody>
<tr><td>alfa</td><td class="foo">bravo</td></tr>
<tr><td class="foo">charlie</td><td>delta</td></tr>
<tr><td>echo</td><td><b>foxtrot</b></td></tr>
</tbody>
</table>
</div>
<script type="text/javascript">
$(document).ready(function() {
var table = $('#demo').DataTable({
"columns": [
null,
null
]
});
// iterate all cell data as a JavaScript array of arrays:
var allData = table.data();
for (var i = 0; i < allData.length; i++) {
var rowData = allData[i];
for (var j = 0; j < rowData.length; j++) {
//console.log("row " + (i+1) + " col " + (j+1) + ": " + rowData[j]);
}
}
// get only one cell - row 3 column 2:
var oneSelectedCell = table.cell(2, 1);
//console.log(oneSelectedCell.data());
// get one cell's <td> node - row 3 column 2:
var oneSelectedCell = table.cell(2, 1);
//console.log(oneSelectedCell.node());
// get some cells using a css class name:
var someSelectedCells = table.cells(".foo").data();
for (var i = 0; i < someSelectedCells.length; i++) {
//console.log(someSelectedCells[i]);
}
// get only one cell without the HTML tags - row 3 column 2:
var oneSelectedCell = table.cell(2, 1);
var node = oneSelectedCell.node();
//console.log(node.textContent);
});
</script>
</body>
The final example shown above...
var oneSelectedCell = table.cell(2, 1);
var node = oneSelectedCell.node();
console.log(node.textContent);
...will print "foxtrot", with the enclosing <b> tag removed.
EDIT:
I forgot one useful function: every(). For example:
// get all nodes using the 'every()' function:
table.cells().every( function () {
console.log(this.node().textContent);
} );
This will list all the table cells' text values (removing embedded HTML, such as the <b> tag).
You can use string manipulation with this matter. You just need to get the indexes between the span tag. indexOf will get the first occurance of a string then use it to get the string you need with substring.
I added +1 on the first index because the start index return the position before the character so plus 1 will do the trick to make it after "<".
var str = "<span class='text-success font-weight-bold'>B81692097</span>";
var res = str.substring(str.indexOf(">")+1, str.indexOf("</"));
document.getElementById("result").innerHTML = res;
<p id="result"></p>
I have an XML file structured like this:
<movies>
<movie>
<title>A title</title>
<year>2016</year>
<boxoffice>18 million</boxoffice>
</movie>
<movie>
<title>Second title</title>
<year>2010</year>
<boxoffice>10 million</boxoffice>
</movie>
<movies>
I want to find all movies after year 2015 and show it in a table using jquery.
I get the xml using:
function getx() {
var x = $.ajax({
url: movies.xml,
datatype: "xml",
async: false
});
return x.responseXML;
}
and go though it using:
function find(year){
var x = getx();
$(x).find("year").each(function() {
if (Number($(this).text()) > Number(year) {
$(document.getElementById("results")).append("<tr><td>" + $(this).text() + "</td></tr>");
}
});
}
This returns creates a table row containing 2016. How could I modify this to search for one element and once found return all elements from the collection it belongs to? (I want to get a table row with title, year and boxoffice)
First: using an ajax call as sync is an issue, I suggest you to use a callback.
Second: in order to convert an xml to a jQuery object you can use jQuery.parseXML( data ). After the conversion you can use .filter() and .each() for selecting the elements you need and append them to the table.
In jquery the ID Selector (“#id”) is:
$('#results')
instead of:
$(document.getElementById("results"))
In order to get the siblings elements you can use: Node.nextSibling and Node.previousSibling or you can use the jQuery.prev() and jQuery.next().
The snippet:
var xml = '<movies>\
<movie>\
<title>A title</title>\
<year>2016</year>\
<boxoffice>18 million</boxoffice>\
</movie>\
<movie>\
<title>Second title</title>\
<year>2010</year>\
<boxoffice>10 million</boxoffice>\
</movie>\
</movies>';
var xmlDoc = $.parseXML( xml );
var jqXml = $(xmlDoc).find('year').filter((idx, ele) => {return +ele.textContent > 2015;});
jqXml.each(function(idx, ele) {
$('#results').append("<tr><td>" + ele.previousSibling.textContent +
"</td><td>" + ele.textContent + "</td><td>" +
ele.nextSibling.textContent + "</td></tr>");
})
td {
border: 1px solid;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table id="results">
</table>
I am trying to style an HTML table row based on values in that row, but I am stuck on step 1 - styling it at all!
Here's the code I have:
<tr id="tablerow<%=j%>">
<script type="text/javascript">
document.getElementById("tablerow<%=j%>").style.backgroundColor = "red";
</script>
<%=j> is pulling a row number in from the loop that's loading the data from the Access database as it loads the table.
The table rows are not showing up as red!
Then later I am going to use some IF statements in Javascript to color the rows based on data from some of the elements:
var datecheck = new Date;
if (document.getElementById("confirmStatus<%=j%>").value=="P" && (document.getElementById("confirmYear<%=j%>").value < datecheck.getFullYear())) {
document.getElementById("tablerow<%=j%>").style.backgroundColor = "LightCoral"; }
I was able to figure it out - thanks for the help!
Have you checked your JavaScript console?
Atleast it should be document.getElementById not document.getElementByID
Your script execute too early - html not ready yet. Try
<tr id="tablerow<%=j%>">
<script type="text/javascript">
window.addEventListener('load',function(){
document.getElementByID("tablerow<%=j%>").style.backgroundColor = "red";
}
</script>
But it's ugly idea do it by js
I find it better to use custom attributes instead of string concatenation:
<tr data-dbid="<%=j%>" style="background-color:red">
<td><input class="confirmYear" /></td>
<td><input class="confirmStatus" /></td>
</tr>
Then use that when needed:
function checkRow(id) {
var _tr = document.querySelector("[data-dbid=" + id + "]"),
_confirmYear = _tr.querySelector(".confirmYear"),
_confirmStatus = _tr.querySelector(".confirmStatus");
if (_confirmYear.value === "P" && _confirmStatus.value < datecheck.getFullYear())
_tr.style.backgroundColor = "LightCoral";
}
window.addEventListener('load',function(){
[].forEach.call(
document.querySelectorAll("[data-dbid]"),
function(el) { checkRow(el.dataset["dbid"]) }
);
});
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 7 years ago.
Improve this question
I have the follow code:
for (var key in returns) {
$('#tBodyTable').append('\
<tr>\
<td >\
<label>'+ returns[key].name +'</label>\
</td>\
<script>\
for (var i in quant_colums){\
document.write("<td ><center><label>a</label></center></td>");\
};\
</script>\
</tr>\
');
};
This code are inside the return of Jquery Ajax, and the first loop overwrite the body the table dynamically. The second loop is for create <td> dynamically based the value of the variable quant_columns, that is why has a javascript there. But I don't know how exactly to do this. Each line of the table will have a number of the columns in determined point, based the result of the query.
How I can do it?
For this case, you do not need to insert a script tag, you can do everything you need in the same function.
$(function(){
var returns = {t1: {name:'teste1'},t2:{name:'teste2'},t3:{name:'teste2'}};
var quant_colums = 3;
var $table = $('#tBodyTable');
for (var key in returns) {
var $tr = '<tr>\
<td >\
<label>'+ returns[key].name +'</label>\
</td>\
</tr>';
for (var i in quant_colums){
$tr.append("<td ><center><label>a</label></center></td>");
}
$table.append($tr);
};
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.1/jquery.min.js"></script>
<table id="tBodyTable"></table>
You can use the DOM to insert elements dynamically based on the data you have like this.
var returns, quant_colums, tbody;
returns = {
a: {name: "a"},
b: {name: "b"},
c: {name: "c"}
};
quant_colums = [0, 1, 2, 3];
tbody = window.document.querySelector("#tBodyTable");
Object.keys(returns).forEach(function (key) {
var row, cell;
row = tbody.insertRow();
cell = row.insertCell();
cell.innerHTML = '<label>' + returns[key].name + '</label>';
quant_colums.forEach(function (i) {
cell = row.insertCell();
cell.innerHTML = "<center><label>" + i + "</label></center>";
});
});
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<script src="script.js"></script>
</head>
<body>
<table>
<tbody id="tBodyTable"></tbody>
</table>
</body>
</html>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>TEST</title>
<link rel="stylesheet" type="text/css" href="/js/jquery-ui-1.8.24.custom.css" media="screen, projection">
<script type="text/javascript" src="/js/jquery-1.8.2.js"></script>
<script type="text/javascript" src="/js/jquery-ui-1.8.24.custom.min.js"></script>
<script type="text/javascript">
<!--
function loadOperators(rowID)
{
alert("ROW: " + rowID);
}
var lastRowID = 1;
// Add new row
$('input#addrow').live('click', function(){
lastRowID += 1;
var $clonedRow = $('tr#row_1').clone();
// manipulating new ids for the elements in the newly created row
$clonedRow.find('*').andSelf().filter('[id]').each(function() {
var string = this.id;
pos = string.lastIndexOf('_');
var tempStr = string.substr(0, pos);
this.id = tempStr + "_" + lastRowID;
});
$clonedRow.insertBefore("#clone_table tr#spacer_row");
$("#field_id_" + lastRowID).on('change', function(){
loadOperators(lastRowID);
});
});
// Delete a row
$('input#delrow').live('click', function(){
if(lastRowID == 1)
{
return;
}
$('tr#row_' + lastRowID).remove();
lastRowID -= 1;
});
$(document).ready(function() {
loadOperators(lastRowID);
$("#field_id_1").on('change', function(){
loadOperators(lastRowID);
});
});
//-->
</script>
</head>
<body>
<table id="clone_table" width="700" cellpadding="0" border="0">
<colgroup>
<col width="200">
<col width="200">
<col width="200">
</colgroup>
<tr id="row_1">
<td>
<select name="field_id_1" id="field_id_1">
<option value="1">Item One</option>
<option value="2">Item Two</option>
<option value="3">Item Three</option>
</select>
</td>
<td id="operator_strip_1"></td>
<td id=""> </td>
</tr>
<tr id="spacer_row"><td colspan="3"> </td></tr>
<tr><td colspan="3"> </td></tr>
<tr><td colspan="3"><input type="button" id="addrow" value="More" /> <input type="button" id="delrow" value="Less" /></td></tr>
</table>
</body>
</html>
I am trying to add and delete rows to a HTML table dynamically.
But the generated row contains one combo box with a onchange event handler function.
I need to pass the row ID to that function. When I assign the new ID to the latest combo box's onchange event handler, it is changing the value assigned to the already generated combo boxes also. Can anyone look this code and tell me what is causing the issue here?
When you reference lastRowID in the call to loadOperators, you're getting the current value, because the variable is not local to the click handler function. You don't need the variable, you can just use this.id.
$('input#addrow').live('click', function(){
lastRowID += 1;
var $clonedRow = $('tr#row_1').clone();
// manipulating new ids for the elements in the newly created row
$clonedRow.find('*').andSelf().filter('[id]').each(function() {
var string = this.id;
pos = string.lastIndexOf('_');
var tempStr = string.substr(0, pos);
this.id = tempStr + "_" + lastRowID;
});
$clonedRow.insertBefore("#clone_table tr#spacer_row");
$("#field_id_" + lastRowID).on('change', function(){
loadOperators(this.id);
});
});
Instead of binding a handler every time you add a row, you could use delegation. Give all the field_id_N elements a class (field_class in the example below), and do this just once in the document.ready function:
$("#clone_table").on('change', '.field_class', function() {
loadOperators(this.id);
});
I'm not sure what the real loadOperators() function does (the one in your question is obviously just a stub), but I suspect you could just pass this to it instead of the ID, and you could probably get rid of all IDs in the elements that get cloned.
If you really need the lastRowID value, you can copy it into a local variable, which will be captured in the closure.
$('input#addrow').live('click', function(){
lastRowID += 1;
var thisRowID = lastRowID;
var $clonedRow = $('tr#row_1').clone();
// manipulating new ids for the elements in the newly created row
$clonedRow.find('*').andSelf().filter('[id]').each(function() {
var string = this.id;
pos = string.lastIndexOf('_');
var tempStr = string.substr(0, pos);
this.id = tempStr + "_" + lastRowID;
});
$clonedRow.insertBefore("#clone_table tr#spacer_row");
$("#field_id_" + lastRowID).on('change', function(){
loadOperators(thisRowID);
});
});