Validation of HTML table generated by WYSIWYG editor in Javascript - javascript

I have a form with several input fields including WYSIWYG editor as an input field. In WYSIWYG editor user enter data using HTML table. But sometime happen while adding new row user enter new table snippet within in the same row as in the below code.
<table width="100%">
<tbody>
<tr>
<td></td>
<td></td>
</tr>
<tr>
<td></td>
<td></td>
</tr>
<tr>
<td></td>
<td>
<table width="100%">
<tbody>
<tr>
<td></td>
<td></td>
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
How can I validate this HTML code snippet using Javascript? How can I identify that within or in table tag (<table) exist. Any help would be appreciated.

You can create an element out of your HTML like this:
function htmlToElement(html) {
var template = document.createElement('template');
html = html.trim(); // Never return a text node of whitespace as the result
template.innerHTML = html;
return template.content.firstChild;
}
const myTable = htmlToElement('<table width="100%">....</table>');
... and then check if there is a table within the table:
if (myTable.querySelector('table')) {
// ...
}
Credits for the htmlToElement function: Creating a new DOM element from an HTML string using built-in DOM methods or Prototype

Related

How to send selected table rows value to another page in javascript

I have 2 pages and 2 tables, in page 1(table 1) I want to send selected rows to page 2(table 2) where in table 2 I show the selected rows
This is the first table in page 1:
<table class="src-table">
<tr>
<th>Select</th>
<th>Firstname</th>
</tr>
<tr>
<td>
<input type="checkbox">
</td>
<td>Jill</td>
</tr>
<tr>
<td>
<input type="checkbox">
</td>
<td>Eve</td>
</tr>
</table>
<br>
<input type="button" value="Submit" id="submit">
Like image below
This is the second table in page 2:
<table class="target-table">
<tr>
<th>Select</th>
<th>Firstname</th>
</tr>
</table>
Like image below
If you really need this. You can use localStorage.
localStorage not working in the sandbox. But you can use it your application as well.
run storeItems when you need to save selected to store (for example on element select)
run appendStoredToAnouther on window event window.onload on page with the target table
function storeItems() {
const selectedItems = document.querySelectorAll("#first-table .selected");
const selectedHtml = nodeListToString(selectedItems);
localStorage.add('selectedTableItems', selectedHtml);
}
function nodeListToString(nodeList) {
let string = '';
nodeList.forEach(function(node) {
string += node.outerHTML;
});
return string;
}
function appendStoredToAnouther() {
const itemsHtml = window.localStorage.get('selectedTableItems');
const targetTable = document.getElementById('target-table');
targetTable.innerHTML = itemsHtml + targetTable.innerHTML;
}
<table id="first-table">
<tr class="selected">
<td>1</td>
<td>Selected</td>
<td>Item</td>
</tr>
<tr class="selected">
<td>1</td>
<td>Selected</td>
<td>Item</td>
</tr>
<tr>
<td>2</td>
<td>Not Selected</td>
<td>Item</td>
</tr>
</table>
<button type="button" onclick="storeItems()">Send to anouther</button>
<button type="button" onclick="appendStoredToAnouther()">Append stored to anouther</button>
<table id="target-table">
<tr class="selected">
<td>1</td>
<td>Selected</td>
<td>Item</td>
</tr>
<tr>
<td>2</td>
<td>Not Selected</td>
<td>Item</td>
</tr>
</table>
Below I demonstrated how some lines could be carried over from one table to another one on a following page. However, since both pages are probably hosted on the same server it is in most cases more practical to first collect some unique identifiers for the selected table records, transmit them to the next page and then get the actual table contents from the original data source again (in many cases a database table or view). This approach will also make your page safer against unauthorised injections.
In case that the tables are to be shown in two consecutive pages you can do the following:
// shortcut for utility function querySelectorAll():
const qsa=(s,o)=>[...(o||document)['querySelectorAll'](s)];
const log=qsa('#log')[0];
qsa('#submit')[0].addEventListener('click',function(){
var dat="tbl="+JSON.stringify(
qsa('tr',qsa('.src-table')[0]).filter(tr=>qsa('input:checked',tr).length)
.map(tr=>qsa('td',tr).slice(1)
.map(td=>td.innerHTML))
);
log.innerHTML+="<hr>dat:"+dat;
log.innerHTML+="\nwindow.location=\"page2.html?\"+encodeURIComponent(dat)";
// this second part would be placed in the onload section if the next page:
log.innerHTML+='var dat=window.location.search.substr(1)'
var args=dat.split("&").reduce((a,v)=>{
var t=v.split('=');
a[t[0]]=JSON.parse(decodeURIComponent(t[1]));
return a;},
{}
);
qsa('.trg-table')[0].innerHTML+=
args.tbl.map((r,i)=>'<tr><td>'+(i+1)+'</td><td>'+r.join('</td><td>')+'</td></tr>').join('');
})
<h2>page one</h2>
<table class="src-table">
<tr><th>Select</th><th>Firstname</th><th>Familyname</th></tr>
<tr><td><input type="checkbox"></td><td>Jill</td><td>Jones</td></tr>
<tr><td><input type="checkbox"></td><td>Eve</td><td>Adams</td></tr>
</table>
<br>
<input type="button" value="Submit" id="submit">
<h2>this would be the second page</h2>
<table class="trg-table">
<tr><th>no</th><th>Firstname</th><th>Familyname</th></tr>
</table>
<pre id="log"></pre>
As this is a sandbox the last lines had to modified a bit. In your page you should actually redirect your page with the window.location assignment.
On the second page you then need to read the passed information from window.location.search and use that information to append it to your table there.

Save whole table html code in a variable

I have a table where the cell content is editable.
Now I want, after I finished editing the table, the html code from the table with all values.
Here is a table:
<table class="table table-bordered content">
<thead>
<tr>
<th>bla</th>
<th>bla bla</th>
<th>bla bla bla </th>
<th>more bla</th>
</tr>
</thead>
<tbody>
<tr contenteditable="true">
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr contenteditable="true">
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
</tbody>
</table>
<button id="save">Save</button>
That's my JS code:
$('#save').on('click', function () {
var table = $('.content').html();
alert(table);
});
The problem is that if I console.log the table variable I get this output:
<thead>
<tr>
<th>bla</th>
<th>bla bla</th>
<th>bla bla bla </th>
<th>more bla</th>
</tr>
</thead>
<tbody>
<tr contenteditable="true">
<td>dwad</td>
<td>dwada</td>
<td>dawdaw</td>
<td>dawdaw</td>
</tr>
<tr contenteditable="true">
<td>daw<br></td>
<td>daw<br></td>
<td>dwadaw<br></td>
<td>daw<br></td>
</tr>
</tbody>
If you have a closer look you can see that the
<table class=" ... "> and the </table> tag are gone but I also need them.
Does someone know what I can do to also get the table-tags ?
Try this:
var table = $('.content')[0].outerHTML;
alert(table);
Should work in every browser
Use outerHTML on the node element. Like this:
$('#save').on('click', function () {
var table = $('.content')[0].outerHTML;
alert(table);
});
Use outerHTML
$('.content').get(0).outerHTML
Check the example on JSfidle
$('#save').on('click', function () {
var table = $('.content')[0].html();
alert(table);
});
This should work.
Use Element.outerHTML
The outerHTML attribute of the element DOM interface gets the serialized HTML fragment describing the element including its descendants. It can be set to replace the element with nodes parsed from the given string.
$('#save').on('click', function () {
var table = $('.content');
alert(table.get(0).outerHTML);
});

jQuery push text from inside / outside of brackets to array

I use json save for a template builder. And I convert some blocks and html tables into simple tags, eg: [[TableName(Title,SKU,Total)]]
The code for this tag looks like this:
<div class="box table">
<table id="TableName">
<thead>
<tr>
<td class="title">Title</td>
<td class="sku">SKU</td>
<td class="total">Total</td>
</tr>
</thead>
<tbody>
<tr>
<td class="title"></td>
<td class="sku"></td>
<td class="total"></td>
</tr>
</tbody>
</table>
</div>
On load, I need to convert tag back to html, so I use:
var tag = []
template.find('.table').each(function(){
var array = $(this).html().match(/\(([^)]+)\)/)[1].split(',');
tag.push(array);
});
console.log(tag)
but I need to get the id too "TableName" than generate the table.
Maybe you need simpler templating engine :
You can try handlebarjs. It's very easy to use and have good performance.
http://handlebarsjs.com/
https://www.youtube.com/watch?v=4HuAnM6b2d8
var $tableID = $(".table").attr("id"); // gets the table's id
var tag = []
template.find('.table').each(function(){
var array = $(this).html().match(/\(([^)]+)\)/)[1].split(',');
tag.push(array);
});
console.log(tag)

checking number of td tags in a dynamic table and divide them into two equal tr tags

The question title might seems ambiguous but I will try to explain in detail over here.
So I am generating a dynamic table based on the JSON data. Inside the table I have few tags and in one of the tag I am further populating table data enclosed in tags. Number of tables inside the td tag might varies but the maximum number of tables are 4. Here is the rough HTML markup which is generated after the table is populated.
Current mark up
<table>
<tbody>
<tr>
<td></td>
</tr>
<tr>
<td></td>
</tr>
<tr>
<td>
<table>
</table>
</td>
<td>
<table>
</table>
</td>
<td>
<table>
</table>
</td>
<td>
<table>
</table>
</td>
</tr>
<tr>
<td></td>
</tr>
</tbody>
</table>
Expected mark up
<table>
<tbody>
<tr>
<td></td>
</tr>
<tr>
<td></td>
</tr>
<tr>
<td>
<table>
</table>
</td>
<td>
<table>
</table>
</td>
</tr>
<tr>
<td>
<table>
</table>
</td>
<td>
<table>
</table>
</td>
</tr>
<tr>
<td></td>
</tr>
</tbody>
</table>
As you can see in the third tag I have 4 tag which contains individual tables. What I am trying to achieve if the number of tags in the third row is greater than 2 then I should create another tag below that and divide the 4 tags (which contains tables) into 2 tags (with 2 tags each).
Since the tables are generated dynamically I don't have a predefined HTML mark up.
This is my relevant JS function
drawRunningDailyDoublesTables: function (events, table) {
var indexes = $(table).data('BetTableData').eventIndexes;
table.innerHTML = '';
// Drawing STAB / NSW product selection
betTable.drawBetTypeProductSelection(table);
// Error space
betTable.drawErrorSpace(table);
var trForTables = $('<tr/>')
.appendTo(table);
// Drawing tables for doubles
$.each(indexes, function(j, index) {
var betTableData = new BetTableData();
betTableData.setMarketId(events[index].markets[0].id);
var doubleTable = $('<table/>')
.data('BetTableData', betTableData);
// Names and info of races
betTable.drawHeaderForDoubles(doubleTable, events[index], 3);
// Horse selections
betTable.drawSelectionsForRunningDoubles(table, doubleTable, events[index], j+1);
// here I am generating the td tag with tables as mentioned in the question. It could be 2,3 or 4 depending on the different situation.
$('<td style="vertical-align: top;"/>')
.appendTo(trForTables)
.append(doubleTable)
// Footer
createFooterRowForRunningDoubles("white", 2, table, doubleTable, j+1);
});
// draw button for betting
betTable.drawExoticBetBtnForDoubles(table);
betTable.selectDefaultRadioProduct(table);
},
Please see this fiddle:
http://jsfiddle.net/MXGBu/2/
var thirdRow = $('table:first>tbody>tr:nth-child(3)');
var tablesInThird = thirdRow.find('table');
if(tablesInThird.length === 4)
{
thirdRow.after('<tr class="arse"></tr>');//creates a new tr after 3rd row
tablesInThird.eq(2).parent().appendTo($('tr.arse')); //adds 3rd table
tablesInThird = thirdRow.find('table');
tablesInThird.eq(2).parent().appendTo($('tr.arse')); //adds 4th table
}

Remove tables from HTML using jQuery

I've got many chunks of HTML coming into my app which I have no control over. They contain tables for layout, which I want to get rid of. They can be complex and nested.
What I want is to basically extract the HTML content from the tables, so that I can inject that into other templates in the app.
I can use jQuery or plain JS only, no server side trickery.
Does anyone know of a jQuery plugin of good tip that will do the job?
Littm - I mean to extract content from the td tags essentially. I want no trace of table left in the code when it's done. Thanks!
Here's an example of the type of HTML in question. It all comes in via XHR from some ancient application so I have no control over the markup. What I want is to get rid of the tables completely, leaving just the rest of the HTML or other text content.
<table>
<tr><td colspan="4"></td></tr>
<tr>
<td width="1%"></td>
<td width="40%" style="padding-left: 15px">
<p>Your access level: <span>Total</span></p>
</td>
<td width="5%">
<table><tr><td><b>Please note</b></td></tr></table>
</td>
<td width="45%" style="padding-left: 6px" valign="top"><p>your account</p></td>
</tr>
<tr><td colspan="4"> </td></tr>
<tr>
<td width="1%"></td>
<td width="40%" style="padding-left: 15px">
<table>
<tr>
<td align="right">Sort Code: </td>
<td align="center"><strong>22-98-21</strong></td>
</tr>
<tr>
<td align="right">Account Number: </td>
<td><strong>1234959</strong></td>
</tr>
</table>
</td>
<td width="5%"></td>
<td width="45%" style="padding-left: 6px">Your account details for</td>
</tr>
</table>
I've tried;
var data = ""
$("td").each(function(){
data += $(this).html()
});
$("article").append(data);
$("table").remove();
But var data still contains nested td tags. I'm no JS expert so I'm not sure what else to try....
Let's suppose that you have X number of tables.
In order to extract all the content information from these, you could try something like this:
// Array containing all the tables' contents
var content = [];
// For each table...
$("table").each(function() {
// Variable for a table
var tb = [];
$(this).find('tr').each(function() {
// Variable for a row
var tr = [];
$(this).find('td').each(function() {
// We push <td> 's content
tr.push($(this).html());
});
// We push the row's content
tb.push(tr);
});
// We push the table's content
content.push(tb);
});
So for instance, if we have the following 2 tables:
<table>
<tr>
<td>1</td>
<td>2</td>
</tr>
<tr>
<td>A</td>
</tr>
</table>
<table>
<tr>
<td>r1</td>
<td>r2</td>
<td>r3</td>
</tr>
<tr>
<td>rA</td>
<td>rB</td>
</tr>
<tr>
<td>rP</td>
</tr>
</table>
The array content will be something like this:
content = [ [ [1, 2], [A] ] ] , [ [r1, r2, r3], [rA, rB], [rP] ] ]
\_______________/ \______________________________/
1st table 2nd table
and if you want to access the first table, you'll just have to access content[0] for instance.
Now, let's suppose that you have a DIV, with and id my_div, and that you want to output some table content in it.
For example, let's suppose that you only want to have the 1st table only. Then, you would do something like this:
// Note: content[0] = [[1, 2], [A]]
var to_print = "<table>";
for(var i=0; i<content[0].length; i++) {
to_print += "<tr>";
for(var j=0; j<content[0][i].length; j++)
to_print += "<td>"+ content[0][i][j] +"</td>";
to_print += "</tr>";
}
to_print += "</table>";
$("#my_div").html(to_print);
which will give you something like this:
<div id="my_div">
<table>
<tr>
<td>1</td>
<td>2</td>
</tr>
<tr>
<td>A</td>
</tr>
</table>
</div>
Hope this helps.
Edit: You should create a recursive function to do that.
Simply create you function that gets "td"'s as a value:
function searchTexts(td) {
if (td.find("td")) {
searchTexts(td.find("td"));
}
td.each(function(){
data += $(this).html()
$(this).remove(); // remove it for avoiding duplicates
});
}
Then call it passing a jQuery object to the function.

Categories

Resources