jQuery isn't creating table row elements - javascript

I'm creating a JavaScript progress bar and the bar itself and the detail message are inside a table. Now, I'm creating this so that all that needs to be in the page is a div and then the class will fill in the rest when it's created. Since it's in a table, the bar and message are supposed to be on different rows, however when I try to create the rows with jQuery they aren't getting generated and the only thing that is getting put in the tables is the two td elements.
The code I currently have is down below. I've tried several different methods to accomplish it that I thought would work.
I have tried using .wrap('<tr></tr>') to try and get it before I put it in the table, and in the call for the table too (i.e. tdMessage.wrap('<tr></tr>') and tdMessage.wrap('<tr></tr>').html()).
I have tried both document.createElement('tr') and just $('<tr></tr>') and calling .html() when putting it in the table.
I feel like there was another attempt in there too...but I can't think of what it was.
var tdMessage = $(document.createElement('td'));
tdMessage.prop('id', this.MessageId.substr(1));
tdMessage.css('text-align', 'center');
//tdMessage.wrap('<tr></tr>');
//var trRow2 = $(document.createElement('tr'));
var trRow2 = $('<tr></tr>');
trRow2.html(tdMessage);
tdMessage = null;
var divBar = $(document.createElement('div'));
divBar.prop('id', this.BarId.substr(1));
divBar.css('width', '0%');
divBar.css('height', '15px');
divBar.css('background', 'url(images/LoadingBarBG.gif)');
var tdBar = $(document.createElement('td'));
tdBar.css('border', '1px #B0B1B1 solid');
tdBar.css('padding', '1px');
tdBar.html(divBar);
//tdBar.wrap('<tr></tr>');
divBar = null;
//var trRow1 = $(document.createElement('tr'));
var trRow1 = $('<tr></tr>');
trRow1.html(tdBar);
tdBar = null;
var tblInner = $(document.createElement('table'));
tblInner.prop('width', '400');
tblInner.prop('cellpadding', '0');
tblInner.prop('cellspacing', '0');
tblInner.prop('border', '0');
tblInner.html(trRow1.html() + trRow2.html());
trRow1 = null;
trRow2 = null;
I'm probably just missing something, but I can't for the life of me figure it out. Everything looks like it should work, and everything else seems to be.
Also, the HTML that it keeps generating is either just putting both td elements in the table without the tr elements surrounding them or it will even just put the bars td and omit the message one.
Thanks for any help.

Don't use .html() because everything you have is a jQuery object, not raw HTML, instead append the cell to the row:
trRow2.append(tdMessage);
trRow1.append(tdBar);
Then append the rows to the table:
tblInner
.append(trRow1)
.append(trRow2);
Do the same with your div when you want to insert it into the cell:
tdBar.append(divBar);

Related

Tampermonkey, Chrome how to automatically insert rows into a table?

I've tried with a stupid way of inserting code for a new table, but not even that seems to work. What would be the proper way?
Here's what I tried to do:
var table = document.getElementsByClassName("test")
[0].getElementsByClassName("tableclass");
for (var i = 0, l = table.length; i < l; i++) {
var content = table[i];
let s = content.innerHTML;
s = s.replace(/table/g, 'table border="1"');
s = s.replace(/tr>[\s\S]*?<tr>[\s\S]*?<td>3/g, 'tr>\r\n<tr>\r\n<td>3');
content.innerHTML = s;
}
And a fiddle: https://jsfiddle.net/d10tk7nr/1/
Also, the reason my stupid way doesn't contain the whole table is because some of the cells where I want to eventually use this would contain random data and I don't know how to skip that.
If you want to create a new HTML-Element, every browser got you covered on that.
var tr = document.createElement('tr');
console.log(tr);
The browser console will show you exactly what you have created - a new HTML element that is not yet part of the DOM:
<tr></tr>
The same goes with the creation of some content for that table row:
var td1 = document.createElement('td'),
td2 = document.createElement('td');
td1.innerText = '5';
td2.innerText = '6';
console.log(td1, td2);
The result will be two td-elements:
<td>5</td> <td>6</td>
Now we have to glue these parts together. Browsers will also have you coverd on this:
tr.append(td1);
tr.append(td2);
console.log(tr);
The result is a complete table row:
<tr><td>5</td><td>6</td></tr>
All we have to do is append this row to your table:
var table = document.querySelector('.test table tbody');
table.append(tr);
The elements you have created are now part of the DOM - child elements of the body of your table to be excact.
Click here for a fiddle
Edit
If you want to insert the new row to a specific place, you have to find the element you that should be next to it and use insertBefore. This would change the the last piece of code to:
var targetTr = document.querySelector('.test table tr:nth-child(2)');
targetTr.parentNode.insertBefore(tr, targetTr);
If you want to choose where to put your new row within your javascript, you can use the childNodes property:
console.log(table.childNodes);
I'd use insertAdjacentHTML, like so:
table[i].insertAdjacentHTML('beforeend', '<tr><td>5</td><td>6</td></tr>');
Please see this fiddle: https://jsfiddle.net/52axLsfn/4/
Also demonstrates how to set the border. Note that this code targets all tables, so depending on your situation you may want to be more specific.

Jquery contenteditable for all cells not rows

I create a table by adding rows and columns with JS and Jquery.
This is my code:
function AddColumnToDataTable(){
$('#tableHeader').append("<th> Header </th>").attr("contenteditable", true);
// Add a new ColumnHeader and set the property "editable"
}
function AddRowToDataTable(){
var count = $('#tableHeader').find("th").length;
// Get the count of Columns in the table
var newRow = $('#tableBody').append("<tr></tr>");
// Add a new Row
for(var i = 0; i < count ; i++){
newRow.find('tr').last().append("<td> Content </td>").attr("contenteditable", true);
// Fill the cells with a default text and set the property "editable"
}
}
So my question is, how can I write the code, that each cell is editable? At the moment, when I click, the whole row goes editable? Each cell should have that property.
I found a code that could help:
//$('table th:nth-child(4)').attr("contenteditable", true)
This makes the 4th header/cell editable, but how can I use it, each new created header/cell is the nth-child?
The jQuery append function doesn't return the new [appended] element, rather it returns the element that was appended to, hence the error in your code. Regardless, it's easier just to set the attribute manually in the append string. So, change this line:
newRow.find('tr').last().append("<td> Content </td>").attr("contenteditable", true);
To this:
newRow.find('tr').last().append("<td contenteditable="true"> Content </td>")
That should do it
It worked with
$('table td').last().attr("contenteditable", true);

Appending to new nodes not yet inserted in the document

In order to make my code concise and reduce unnecessary dom rendering, I'm trying to construct and populate a table before appending it to the document. The problem I'm having is that only the divs are getting appended to the table, so I end up with a table full of divs instead of tr's with td's that contain divs.
I'm pretty sure this is because when I use the .appendTo function it's not appending the td to the tr, and the tr to the table but instead is removing the div and appending it to each in turn, lastly ending up in the table.
How can I construct a node chain before appending to the document?
Code:
var playerSelect = $( "#playerSelect" );
var playerElements = [];
var rowCounter = 0;
var playerTable = $("<table/>").attr("id", "playerTable");
for (player in playerBase){
var playerDiv = $("<div/>").addClass("player").text(player + playerBase[player].rating);
playerDiv.appendTo("<td/>").appendTo("<tr/>").appendTo(playerTable);
};
playerSelect.append( playerTable );
.appendTo() does not accept a string value. $() does however, so you could change your code like this:
$("<tr />").append($("<td />").append(playerDiv)).appendTo(playerTable);
That said, this is not the cleanest way to do it, you might want to have a look at templating engines if you have a lot of these structures in your code.
for (player in playerBase){
var tr = $('<tr/>');
var td = $('<td/>');
td.appendTo(tr);
var playerDiv = $("<div/>").addClass("player").text(player + playerBase[player].rating);
playerDiv.appendTo(td);
tr.appendTo(playerTable);
};

Jquery Mobile Table Reflow

I'm trying to create my own script for a mobile version of my tables on my website.
Im currently using the script below to get the size of the table, and create new tables for each row, duplicating the headers into each new table.... (see: http://api.jquerymobile.com/table-reflow/ ) to get an idea of what I'm trying to achieve.
My script is as follows, but their is a js fiddle included at the bottom for a better example.
My problem is that I am only able to create 1 inside each table, where it should really be 3 rows, inside of each table. Again check the fiddle below for a proper example. Can anyone see why it is only creating 1 row in the table?
<script>
$(document).ready(function(){
var TableSize = $("table thead tr th").not("table.mobile_table thead tr th").size(); // Get # of columns
var i = 1;
var TableRowCount = $("table tbody tr").size(); // Get # of body rows
$("table thead tr th").each(function(){
$(this).attr("id", i++); // Give headers incrementing ID
});
for ( var CreateTables = 1; CreateTables < TableRowCount; CreateTables++ ){ // Create new table class="mobile_table" for each row
$("table").after("<table class='mobile_table'></table>");
}
$("table.mobile_table").each(function(){// Insert original headers into each row of new table as first column
var h = 1;
while ( ++h < TableSize){ // this is where the error is, it gives me the stuff below but x3 (the number of created tables)......
$("table.mobile_table").after("<tr><td></td><td></td><td></td></tr>");
}
});
console.log(TableSize);
console.log(TableRowCount);
});
</script>
See the fiddle: http://jsfiddle.net/Yf7KV/
Do you mean like this: http://jsfiddle.net/Yf7KV/2/
JS
$(this).append("<tr><td class='mobile_col_1'>Col 1</td><td class='mobile_col_2'>Col 2</td></tr>");
Explanation: Append will alllow you to append elements one after the another. html replaces with what you currently have

injecting arbitrary HTML string into document (javascript) - updated

Update: I just narrowed my problem to this:
Why doesn't this work:
var tmp = document.createElement('tbody');
tmp.innerHTML="<tr><td>hello</td></tr>";
tmp is getting the string hello. the tr and td html is lost (on FireFox).
Why is that? and how can I make such html injection work?
Original question:
I need to inject arbitrary HTML after a arbitrary element in arbitrary HTML documents.
I came across this method (inject the html string into dynamically generated div, get its firstchild element and insert it in the right place):
var tmp = document.createElement('div');
tmp.innerHTML = _injected_html;
var new_w = tmp.firstChild;
var parent = insertion_point.parentNode;
parent.insertBefore(new_w, insertion_point.nextSibling);
The problem is that this does not work when trying to inject table elements.
if the injected html is for example
"<tr> <td> table data </td> </tr>"
The _tmp.innerHTML = _injected_html; would not accept it (adding tr under div element).
Any idea how to make this work for any tag?
Are you testing in IE by any chance? Most likely it does work in other browsers.
Here's why
edit: Wait, you're inserting something into the table that looks like <div><tr><td>... that's not going to work. Why don't you replace the document.createElement('div') by document.createElement('tr'), and remove the <tr> tags from the _injected_html?
Something like this (tested in Firefox):
<script>
var i = 3;
function f() {
var table = document.getElementById('someTable');
var children = table.children[0].children;
var after = children[Math.round(Math.random() * (children.length - 1))];
var html = "<td>" + i++ + "</td>";
g(html, after);
}
function g(_injected_html, insertion_point) {
var tmp = document.createElement('tr');
tmp.innerHTML = _injected_html;
var new_w = tmp.firstChild;
var parent = insertion_point.parentNode;
parent.insertBefore(new_w, insertion_point.nextSibling);
}
</script>
<table id="someTable" onclick="f();">
<tr><td>1</td></tr>
<tr><td>2</td></tr>
</table>
The second line of f() is a little awkward, but it gets the first child of the table (which is a <tbody>, and then its children (the actual <tr>s).
<div><td><lol/>
..isn't valid HTML! Containers are required for table rows/cols/heads, list items, definition lists and so on. Could you somehow validate the HTML for proper containers before injecting it?
The following javascript will allow you to inject HTML/etc into the local page:
var example = "<p>test</p>"
document.body.appendChild(example);
That said, you will have to customize the code depending on what you are inserting.
For a table, you must insert tr's into tbody. When you write html
<table><tr><td>abc</td></tr></table>
IE, FF, Chrome, Safari at least (don't know about others directly) will modify this to be:
<table><tbody><tr><td>abc</td></tr></tbody></table>
Therefore, something like:
var tmp = document.createElement('tr');
tmp.innerHTML = "<td>def</td>";
var new_w = tmp.firstChild;
var parent = insertion_point.parentNode;
parent.insertBefore(new_w, insertion_point.nextSibling);
if insertion_point is a tr tag.
But honestly, with Jquery there are more elegant ways of going about this as christina toma notes.

Categories

Resources