Make html layout and use it with JS - javascript

I have a table with some data:
<table id="myTable">
<thead>
<tr>
<th><h1>Name</h1></th>
<th><h1>Picture</h1></th>
<th><h1>Likes</h1></th>
<th><h1>Time</h1></th>
</tr>
</thead>
<tbody>
***loop***
<tr>
<td>{placeholder1}</td>
<td><img src="{placeholder2}" alt=""></td>
<td>{placeholder3}</td>
<td>{placeholder4}</td>
</tr>
***end loop***
</tbody>
</table>
I have a js function who gets some data from server by POST request every 10 minutes. <tr></tr> block needs to be repeated several times.
HTML code become more and more complex and I need a solution with layouts and placeholders. I need a direction to search :)
All I need is:
Store <tr></tr> pattern with placeholders to insert it into my webpage. How could I achieve it with js?
How could I mark the places where I need data to be inserted?

Okay since you are using jQuery,
This may be your HTML
<table>
<tbody id="myTableBody">
<!-- Your elements will be placed here -->
</tbody>
</table>
I will assume you are using $.ajax or $.post in either of those, add a callback function property success
$.ajax({
// ... your properties,
success: function(data) {
// basic template for of your "tr"
var trTemplate = [
'<tr>',
'<td></td>',
'<td><img src="" alt=""></td>',
'<td></td>',
'<td></td>',
'</tr>'
].join('')
// get the tbody elemen
var $myBody = $('#myTableBody')
// if you want to clean up the current content of $myBody,
// if it is not the case just remove the following line
$myBody.empty()
// assuming data is an array of elements / entities
data.forEach(function(element){
var $tr = $(trTemplate)
$tr.find('td').eq(0).text(element.placeholder1)
$tr.find('img').attr('src', element.placeholder2)
$tr.find('td').eq(2).text(element.placeholder3)
$tr.find('td').eq(3).text(element.placeholder4)
$myBody.append($tr)
})
}
})
This is example of how you could do it, there are many ways to improve this for performance and so on. Please use it only as reference

If you're using jQuery then this is pretty straightforward. You need to id your elements so that you can reference them individually. Say you start with:
<tr id="tr-0" >
content...
</tr>
and then in javascript..
var id = $('#tr-0').attr('id');
var num = parseInt(id.substring(3));
num++;
$('#tr-0').after('<tr id='+num+'>content...</tr>');
obviously you need to figure how you're getting the content for each row but hopefully you can see that it wouldn't be too hard to fill each row with custom data.

Although you can use jQuery, simpler ways exist. jQuery will require you to add additional steps that aren't really necessary. If you want to use as few Javascript packages as possible, go with jQuery.
But, I highly recommend Vue.js for Laravel projects. There are instructions from Laracasts on how to set it up. But, I have created a jsfiddle with a working set of Vue.js with the v-for directive. Checkout the JSFiddle here.
If you have questions, I'll answer as much as I can.

Related

jQuery selector does not work in dynamically inserted data

I have a problem selecting an element from the html throght jQuery. It could be maybe the fact that the element i am trying to access is dynamically insterted throught getJson, but of course before executing the following js.
What can be the problem and how can be solved?
<table id="myTable">
<tbody>
<!-- inserted with getJson -->
<tr>
<td> <input type='checkbox' id="myInput0"> </td>
<td class="myClass">some text</td>
</tr>
<!-- other rows -->
</tbody>
</table>
var id = "myInput" + 0;
var text = $("#"+id).closest('tr').find('td.myClass').text();
alert(text)
I tried to recreate the scenario using getJSON and inserting an element dynamically, then you can do something like this:
$( document ).ready(function() {
const url = 'https://jsonplaceholder.typicode.com/todos/1';
$.getJSON( url, function( data ) {
$('#main').append(data.title);
});
});
codepen
hope it helps :)
Take a look at this Stack Overflow Q&A - How do I attach events to dynamic HTML elements with jQuery? - there are a few approaches you can take, but the jest of it is that you need to bind to the body or container of your element rather than the element itself.
Welcome to the community user21! Hopefully that info is helpful.

How to convert a JSON tree to a dynamic HTML table

(First allow me to say that I'm just beginning to learn Node-RED concepts; I went through some beginners' guides at nodered.org, and now am trying to extend what I learned so far).
I'm trying to build a flow that starts with a simple JSON tree like
[{"position":"1", "title":"element #1"},
{"position":"2", "title":"element #2"},
{"position":"3", "title":"element #3"}]
To build that treee I use a template node, property is set to msg.payload.
The number of array elements (in theory) is dynamic. To make sure that this tree is true JSON I added a JSON node converting from String to JSON object.
Next I wish to parse that object into a dynamic html table. For this I used a JS function node that's looping through the object and embedding its elements into the according html elements like this:
var return="";
for(var i=0;i<=msg.payload.length-1;i++){
var row=msg.payload[i];
if(row){
return+="<tr>";
return+="<td>"+row.position+"</td>";
return+="<td>"+row.title+"</td>";
return+="</tr>";
}else{
return+="no object at index "+i.toString();
}
}
msg.payload=return;
return msg;
The output of the function then should be passed into a 2nd template like this:
<html>
<head></head>
<body>
<table border="1">
<tr>
<td>#</td>
<td>Title</td>
</tr>
{{ payload }}
</table>
</body>
</html>
I would have expected that the function's result is inserted into the static table of my template, and that happens indeed but not the way I hoped: somehow the html elements that got created by my function are not recognized as what they shoud be; instead I see that they are rendered as
<tr><td>1</td><
instead of
<tr><td>1</td>
etc.
Result is that the browser does not recognize those elements and prints them together with their contents outside my static table
Questions:
what do I need to do so that my 2nd template recognizes my computed string as a set of html elements?
or is this probably a concept not suitable for my purpose?
I'm assuming you are using handelbars for your templating engine. In that case use:
{{{ payload }}}
Instead of
{{ payload }}
However a more elegant approach would be this:
<html>
<head></head>
<body>
<table border="1">
<tr>
<td>#</td>
<td>Title</td>
</tr>
{{#each payload}}
<tr><td>{{this.position}}</td><td>{{this.title}}</td></tr>
{{/each}}
</table>
</body>
</html>
then just
return msg.payload
again thanks to #als9xd for pointing me into the right direction; his 2nd idea indeed sounds much more elegant but first I couldn't get it to work. After some trial-and-error and looking up documentation for the template node I finally came up with this: removed the function node from my original question and then altered the 2nd template to this code:
<html>
<head></head>
<body>
<table border="1">
<tr>
<td>#</td>
<td>Title</td>
</tr>
{{#payload}}
<tr>
<td>{{position}}</td>
<td>{{title}}</td>
</tr>
{{/payload}}
</table>
</body>
</html>
Difference to #als9xd's example is that I replaced {{#each payload}} with a simple {{#payload}}, plus omitted this when referencing the object keys.
Could this be due to different Node-RED versions?
Anyways this is starting to be much fun!

.each() function on affect current object

having some issues with my code below, first here is the HTML:
<table class="finance-table">
<tbody><tr>
<th></th>
<th>Deposit</th>
<th>Balance</th>
<th>Fees</th>
<th>Total Payable</th>
<th>Term</th>
<th>Fixed Rate</th>
<th>Representative APR</th>
<th>Monthly Pmt</th>
</tr>
<tr class="hp">
<td><strong>HP</strong></td>
<td id="td_finance_deposit">£11700.00</td>
<td id="td_finance_balance">£105300.00</td>
<td id="td_finance_fees">£298.00</td>
<td id="td_finance_total_inc_deposit">£146255.50</td>
<td id="td_finance_term">60 mths</td>
<td id="td_finance_rate">5.50%</td>
<td id="td_finance_apr">10.1%</td>
<td id="td_finance_monthly_payments">£2242.59 p/m* x 60 mths</td>
</tr>
</tbody></table>
There is about 10 of these tables [within the same document], all with the same id's and class's. I'm using an each loop to execute some code against each table found, however it only seems to be working on the first table and disregards the others.
Below is the jQuery, like I said works find on the first table, but ignores the rest!
<!-- Remove First and Final Payment from Showroom Finance Examples -->
<script>
$(".finance-table").each(function(key, value) {
// Display loading
var html = $(this);
// Remove the First Payment and Final Payment Column
$(this).find("#td_finance_first_payment, #td_finance_final_payment").remove();
$(this).find("th:contains('1st Pmt')").remove(); $(this).find("th:contains('Final Pmt')").remove();
// Get the Term and update the monthly payment
var term = $(this).find("#td_finance_term").html(); // .replace(/\D/g,'')
var payments = ($(this).find("#td_finance_monthly_payments").html()).split('x')[0];
($(this).find("#td_finance_monthly_payments")).html(payments + " x " + term);
})
</script>
Edit:
Please note, I can't change the HTML at all
You should first give a unique ID to each <td>, perhaps with your DB identifier for that record. You don't need it now but this will allow you to do other thing later if you need it.
Then change all the <td> ids to classes:
<td class="td_finance_fees">£298.00</td>
Finally change all your javascript accordingly to use class instead of IDs:
$(this).find(".td_finance_first_payment, .td_finance_final_payment").remove();
Using Attribute Equals Selector
Change your code from:
$(this).find("#td_finance_first_payment, #td_finance_final_payment").remove();
to:
$(this).find('td[id="td_finance_first_payment"], td[id="td_finance_final_payment"]').remove();
Do this type of change for all areas of #xxx to id="xxx"
What this does is find all tds with attribute id="xxx", rather than using #id identifier, this is forces jQuery to do a tree search.
Also your HTML does not match your code, (theres no td_finance_first_payment in your html, I assume you removed it?)
Edit: This solution is useful if you 100% cannot edit the html (comes from a source you have no control over, such as an API or internal software). Best solution would be to fix the ids!

removing inner table filter bootstrap

I have a filterable table containing a collapsible list in a column. The collapsible contains another table. Sample of the situation.
The problem is that when anything is written to filter only the required items, the inner table also gets filtered. Is there a way to avoid this.
Suggestions about how else to display something like this are also welcome.
If you want to filter only from the Name column, you can try to use below code:
$('#filter').keyup(function () {
var stringValue = $(this).val();
$("#outer-table tr.row").each( function( index ) {
$(this).hide();
$(this).find(".panel-title a:contains("+stringValue+")").parents("tr").show();
});
});
EDIT: I have tested the new code above, it works as expected.
HTML changes, easier to get ONLY every <tr> that are part of your outer-table:
Change your outer-table tag from <tbody class="searchable">, into this, <tbody id="outer-table" class="searchable">
Then add a selector to every <tr> inside outer-table but NOT inside inner-table, like this:
</tr>
<tr class="row">
<td><div id="collapsibleMain2" class="panel-group">
</tr>
<!-- and so on -->
For more info about the jQuery functions that I used above:
contains
each
hide

tablesorter multiple dynamic tables on one part

Hi I am totally stuck on this one.
I am using tablesorter on data pulled from a mysql database.
The problem is, based on criteria, I can have multiple tables pulled and displayed.
My problem is that tablesorter will only sort the first table instance.
This is the code I am using for the tablesorter. Basic use of it.
<script type="text/javascript" >
$(document).ready(function()
{
$("#table-2").tablesorter();
}
And this is how I pull the data and use it with tablesorter.
It is the Branchname that can change. If a user is assigned more than one branch they get multiple tables. This is where I'm stuck on implementing tablesorter on any table past the first instance.
$result=mysql_query("SELECT id FROM users WHERE username='$username'");
$idary=mysql_fetch_assoc($result);
$id=$idary['id'];
$result0=mysql_query("SELECT branch_id FROM access WHERE userid='$id'");
while ($row1=mysql_fetch_assoc($result0))
{
$branch_id=$row1['branch_id'];
$result=mysql_query("select distinct(name) from location where id='$branch_id'");
$nameary=mysql_fetch_assoc($result);
$branchname=$nameary['name'];
?>
<table>
<thead>
<b><br><?echo $branchname; ?></b>
</thead>
</table>
<div>
<table id='table-2' class='tablesorter'>
<thead>
<tr>
<thCreator</th>
<th><center>TeamName</th>
<th><center>Tech Tot</th>
<th><center>Tot W/O</th>
<th><center>Tot S/C</th>
</tr>
</thead>
// get team creators from province
$result1=mysql_query("select distinct(teamcreator) from techteams where....
I'm thinking I would need to use some form of incrementing tablename to match the number of tables pulled but I'm stuck on how to do this.
I could be wrong on that assumption and there might be a much easier way of doing this.
If anyone has any pointers in the right direction I'd love some tips.
Cheers,
-Colin.
you could try to give your tables an own class instead of an id.
<table class='mytables'>
<script type="text/javascript" >
$(document).ready(function()
{
$(".mytables").tablesorter();
}
</script>
or maybe only give them the table-sorter class and in your script you try something like this:
$("table").tablesorter();
Try it:
$(".tablesorter").tablesorter();

Categories