I need some help to dynamically load data in a template as a file change. Below is a sample of the data and code
I have a json file:
data = '[{"name" : "bob", "value" : "3.1"}, {"name" : "joe", "value" : "5.6"}]';
The value in this file change regularly (every 2-3 sec)
I have an HTML file
<head>
<script type="text/javascript" src="data.json"></script>
<script type="text/javascript" src="javascript.js"></script>
</head>
<body>
<table>
<tr>
<td>0</td>
<td>0</td>
</tr>
<tr>
<td>0</td>
<td>0</td>
</tr>
</table>
<body>
<script type="text/javascript">
document.body.innerHTML = markup;
</script>
And javascript.js is:
var mydata = JSON.parse(data);
const markup = `
<table>
<tr>
<td>${mydata[0].name}</td>
<td>${mydata[0].value}</td>
</tr>
<tr>
<td>${mydata[1].name}</td>
<td>${mydata[1].value}</td>
</tr>
</table>
`;
So the first question is: how can I get the data dynamically loading in the template as the value change? jQuery? node.js? I need the most simple solution as I am not a newbie.
And secondly, the html code is a bit more complex in reality, but is there a relatively simple way to loop through the data rather than me having to write everything manually? like introducing a "foreach d in data" ?
Thanks for your help, much appreciated!
1.Nodejs[Expressjs] [ server side ]
2.Fetch() and setInterval()[ client side ]
Assuming you have set up the the functions/code regarding the values changing in the initial json file.
What you can do is use nodejs and expressjs on the server side to send the data(maybe json format?) when pinged, and on the client side what you can do is create a function in js(maybe using fetch()) to ping that nodejs server every 'x' second's using setInterval() and retrieve the data parse it if it's json and change the data in table's.
Regarding the data in the tables, someone has already posted a solution for it.
Hope it helps!
I hope I've been helpful
HTML:
<table id="myTable">
</table>
Javascript:
var x = document.getElementById("myTable");
setInterval(function(){
// Here you get the file in the way that is most convenient for you
// More info here: https://www.w3schools.com/js/js_json_parse.asp
var data = '[{"name" : "bob", "value" : "3.1"}, {"name" : "joe", "value" : "5.6"}]';
var obj = JSON.parse(data);
// Clear the table
x.innerHTML = '';
// Adds new values
for (var key in obj[0]) {
if (obj[0].hasOwnProperty(key)) {
x.innerHTML += '<tr><td>'+key+'</td><td>'+obj[0][key]+'</td></tr>'
}
}
}, 1000);
Related
I'm loading a datatable using json data saved in an online url. The problem is, when the data gets large (in this case, 10,000+ rows), the datatable takes way too long to load (30+ seconds).
I'm wanting to make it so that it will load only the values needed for the page. At the moment, it's paginated so that about a dozen values show on the page, but I think it's slow because it's loading the entire dataset first.
Is there a way to make it so that only those dozen values load first - rather than wait for the whole thing to load?
It needs to still be responsive to several click/search events, so that when the user searches or clicks several filters, the datatable updates - but I would again prefer that it only shows the first page of results.
Code
const url = 'https://raw.githubusercontent.com/________________.json';
async function populate() {
const response = await fetch(url);
const evidenceData = await response.json();
console.log(evidenceData)
// Build Table
function buildTable(data) {
var table = document.getElementById('myTable')
table.innerHTML = data.map(function(row) {
let [country, title, category, date, link, image] = row;
return `<tr>
<td>
<br><br>
<a href="${link}" target='_blank'>
<img class="tableThumbnail" src=${image}><br><br>
</td></a>
<td>
<span class="tableTitle"><br><br><a href="${link}" target='_blank'>${title}</a><br></span>
</td>
<td>${country}</td>
<td>${category}</td>
<td>${date}</td>
</tr>`;
}).join('');
}
$(document).ready(function() {
var oTable = $('.mydatatable').DataTable({
"dom": "<<t>ip>",
"columnDefs": [{
targets: [2, 3, 4],
visible: false,
searchable: true,
}]
});
$('#searchInput').keyup(function() {
oTable.search($(this).val()).draw();
});
})
buildTable(evidenceData)
}
populate();
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/popper.js#1.14.7/dist/umd/popper.min.js" integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap#4.3.1/dist/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"></script>
<!-- Datatables -->
<link rel="stylesheet" href="https://cdn.datatables.net/1.12.1/css/jquery.dataTables.min.css">
<script src="https://cdn.datatables.net/1.12.1/js/jquery.dataTables.min.js"></script>
</head>
<body>
<form class="form">
<div>
<input type="text" id="searchInput" class="form-control" placeholder=" Search">
</div>
</form>
<div class="main">
<table class="table mydatatable" id="mydatatable">
<thead>
<tr>
<th> </th>
<th> </th>
<th> </th>
<th> </th>
</tr>
</thead>
<tbody id="myTable">
</tbody>
</table>
</div>
</body>
I've tried a few things here and there with ajax but am not really having much luck in getting it working with this json that is stored on an online url.
Short answer - not possible.
Longer one: a JSON file represents serialized data. Therefore, it must get to its end before parsing it. Imagine the following scenario:
{
"rows": [
{ "id": 1 },
{ "id": 2 },
// --> you want it split up until here
{ "id": 5 },
]
}
Let's say JSON can parse this. What would be the length of rows? It cannot be 3, because the list was split into chunks and each chunk does not contain equal amount of items. You want to split it until 2, but tomorrow it might be 5. Because it's arbitrary, JSON parser cannot imagine all variations you'd like to have. And keep in mind this is a standard mechanism for data manipulation - what would you do for objects? :)
In your case, there's not much to do since you don't control the JSON file generation. If you want to load something huge, well, you have to wait for it :) You can use some techniques to not block the UI, but that won't save you time.
I am trying to figure out the best way to convert multiple HTML strings to PDFs (client side), add those to a .zip file (preferably using JSZip) and then downloading that .zip file.
Here is some code to try and accomplish this...
// HTML examples to render
var tableHtml = `<table>
<tr>
<th>Company</th>
<th>Country</th>
</tr>
<tr>
<td>Alfreds Futterkiste</td>
<td>Germany</td>
</tr>
<tr>
<td>Centro comercial Moctezuma</td>
<td>Mexico</td>
</tr>
</table>`
var boldHtml = "<p> Hello <strong>World</strong> </p>"
var imageHtml = `<h1> City </h1>
<img src="https://images.unsplash.com/photo-1582010905429-bef463482aa2?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1000&q=80">`
var htmlToConvert = [tableHtml, boldHtml, imageHtml];
// Convert (using jsPDF, but totally open to other options... As this doesn't work)
let fileNumber = 1;
for (const html of htmlToConvert) {
let jsPdf = new jsPDF();
jsPdf.html(html); // This right here seems to be what I can't get working...
zip.file(`file${fileNumber}.pdf`, jsPdf.output('blob'), { binary: false });
fileNumber++;
}
// Save .zip file
const blob = await zip.generateAsync({ type: 'blob' });
const fileSaver = await import('file-saver');
fileSaver.default.saveAs(
blob,
`example.zip`
);
This code doesn't work, I think it's specifically the line jsPdf.html(html) that doesn't work. Once the .zip downloads there are 3 PDF files, but they are all blank with no content.
If I replace jsPdf.html(html) with jsPdf.text(html, 1, 1) that seems to work, but it's just plain html, so nothing is rendered. I did take a look at this SO post and downgraded accordingly, but with no luck.
"html2canvas": "1.0.0-alpha.12",
"image-conversion": "^2.1.1",
jsPdf.html does have a callback option on it, so I also tried the following code:
pdf.html(document.body, {
callback: function (pdf) {
zip.file(`file${fileNumber}.pdf`, pdf.output('blob'), { binary: false });
}
});
However, the problem here is that the callback probably isn't being triggered until after the zip file saves, so the .zip will just be empty. Not sure exactly how to utilize the callback in this case? I might just be missing something obvious here.
I am open to using tools other than jsPdf to accomplish this task, any ideas?
Thank you! :)
The issue is that you need to wait for the all the conversions to complete before you save the zip file. You can do this by wrapping the callback in a Promise in order to work with your existing awaits:
await Promise.all(htmlToConvert.map((html, fileNumber) => {
const jsPdf = new jsPDF();
return new Promise<void>((resolve, reject) => {
jsPdf.html(html, {
callback: function (pdf) {
zip.file(`file${fileNumber}.pdf`, jsPdf.output("blob"), { binary: false });
resolve(); // maybe reject if jsPdf is able to signal some kind of error condition?
},
});
})
}));
In comments I suggested this may not be the method to use with a zip function since all PDF contents are transported via the html to the clients device for generation in their cpu and local resources. In fact I was surprised to see the external image in file 3 was not blocked by CORS policy.
The generation of 3 files in one run triggers a response from the browser requesting allow multiple downloads thus this multi generate files is not ideal as the downloads after the 1st need to be reselected from download dialog.
However to provide a direct answer to your core question
doc.html({html}); // This right here seems to be what I can't get working...
here is a draft to work from.
<!DOCTYPE html>
<html lang=en>
<head>
<title>Title of the document</title>
<style>
</style>
</head>
<body>
<script src="https://code.jquery.com/jquery-2.1.3.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jspdf/1.5.3/jspdf.debug.js" integrity="sha384-NaWTHo/8YCBYJ59830LTz/P4aQZK1sS0SneOgAvhsIl3zBu8r9RevNg5lHCHAuQ/" crossorigin="anonymous"></script>
<script src="https://html2canvas.hertzen.com/dist/html2canvas.js"></script>
<script>
//
// HTML examples to render BEWARE sub canvas .css defaults mess with scales thus styles/widths may not be as expected the common div wrapper value ${html} below may need tweaking
var Html1 = '<table><tr><th>Company</th> <th>Country</th></tr><tr><td>Alfreds Futterkiste</td> <td>Germany</td></tr><tr><td>Centro comercial Moctezuma</td> <td>Mexico</td></tr></table>'
var Html2 = '<p>Hello<strong> World</strong></p>'
var Html3 = `<h1> City </h1><img src="https://images.unsplash.com/photo-1582010905429-bef463482aa2?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=460&q=80">`
var htmlToConvert = [Html1, Html2, Html3];
// Convert (using jsPDF, but totally open to other options... As this doesn't work)
// set counter to 0
let fileNumber = 0;
for (const html of htmlToConvert) {
fileNumber++;
var doc = new jsPDF({
orientation: 'p',
// unit MUST be pt for .html inclusion
unit: 'pt',
format: 'a4'
})
// remember these values are printers point sizes not mm or pixels
doc.setFontSize(10);
// optional heading text, x(pt), y(pt), var, var, 'alignment' NOTE variable fileNumber set above works for the heading
doc.text(`File ${fileNumber}`, 298, 10, null, null, 'center');
// doc.html({html}); // This right here seems to be what I can't get working...
// Convert HTML to PDF in JavaScript ensure the file names are different
let name = `File${fileNumber}`
doc.html(`<div style=width:1350px>${html}</div>`, {
callback: function(doc) {
doc.save(`${name}.pdf`);
},
x: 10,
y: 10
});
}
</script></body></html>
I am using a node js backend and express-handlebars as template for front end. I am fetching json file from my mysql db and sending it to my dashboard.hbs file. The problem is the json is going to the browser and as long as it is accessed from the html its showing everything right but inside the script it going crazy. Can any one tell me what am I doing wrong I have gone through a lot of sites along with this and this. none of these work. I also used register helper in my hbs for stringyfying json but still its showing me strange converted json. here goes my codes
exports.dashboard = function (req, res) {
//var dashboards=dashboardModel.findAll({ include: [{ all: true }]});
var dasboard = null;
dashboardModel.findAll().then(dasboards => {
dasboard = dasboards;
if (dasboard.length > 0)
console.log(dasboard[9].monster);
else
console.log('no dashboard');
var jsss=JSON.parse(dasboard[9].monster);
var st=JSON.stringify(jsss);
console.log(st);
res.render('dashboard', {
dasboard: dasboard,
js:jsss
});
})
}
and here goes my template
<!DOCTYPE html>
<html>
<head>
<title>FaceMask API</title>
</head>
<body>
<h2>The list of Monsters</h2>
{{#if dasboard}}
<table>
<tr>
<th>PRODUCT ID</th>
<th>GIF_ID</th>
<th>GIF_TITLE</th>
<th>PRICE</th>
<th>Monster </th>
<th>GIF_PACK</th>
</tr>
{{#each dasboard}}
<tr onclick="gotoEditDashboard('{{this.id}}')">
<td>{{this.product_id}}</td>
<td>{{this.gif_id}}</td>
<td>{{this.gif_titile}}</td>
<td>{{this.price}}</td>
<td>{{this.monster}}</td>
<td>{{this.gif_pack}}</td>
</tr>
{{/each}}
</table>
{{else}}
<p> No Data Available {{dasboard}}</p>
{{/if}}
<script src="javascripts/dashboard.js"></script>
<script type="text/javascript">
var j="{{{ js}}}";
//var jsss=JSON.parse(j);
console.log(j[2].toString());
//console.log("asd: "+jsss[0].fileName);
</script>
</body>
</html>
I printed the json in my server its like
[{"fileName":"blob_1527417588127.jpg","fileLink":"localhost:3000/img/blob_1527417588127.jpg"},{"fileName":"blob_1527417588127.jpg","fileLink":"localhost:3000/img/blob_1527417588127.jpg"}]
but in the browser I get only an object of which if I try to parse it as json or try to use it directly error occurs. I already said that I tried using registerHelper for express-handlebars if it do it then I get following json
[{"fileName":"blob_1527417588127.jpg","fileLink":"localhost:3000/img/blob_1527417588127.jpg"},{"fileName":"blob_1527417588127.jpg","fileLink":"localhost:3000/img/blob_1527417588127.jpg"}]
The strange thing is in the html part I am printing the monster json as well there it shows perfectly but when I am printing from my script its going crazy. Can anyone help me out??
This is just strange but I found the answer to my own question. May be it will help some one falling in the same pit as me. So in the script inside html file you write the following to decode and array of json object
{{#each js}}
var obj = {};
{{#each this}}
obj.{{#key}} = '{{this}}';
{{/each}}
m.push(obj);
{{/each}}
And this is what you write in the server.
var k=[];
var s={
"a":"as",
"b": "ee"
};
var s1={
"a":"ast",
"b": "eet"
};
k.push(s);
k.push(s1);
app.get('/', function(req, res){
res.render('index', {js:k});
});
Not sure what is going on , but I'm not getting anything to display on my web page with ng-repeat with template.
Here is a picture image showing the data
This pic shows my console.log output with array of objects
NO IDEA why doesn't just display on the web page!
Devices: Array[17]
0 : Object
Aid : "....."
...
1 : Object
Angular controller with function
(function () {
'use strict';
angular.module('app').controller('DeviceController', DeviceController);
function DeviceController($http){
var vm = this;
var dataService = $http;
//dataService.get("/api/Product")
vm.devices = [];
deviceList();
function deviceList() {
dataService.get("http://localhost:42822/api/device")
.then(function (result) {
vm.devices = result.data;
//debugger;
console.log(vm.devices);
},
function (error) {
handleException(error);
});
}
function handleException(error) {
alert(error.data.ExceptionMessage);
}
}
})();
HTML
<html>
<head> </head>
<body>
<div ng-app="app" ng-controller="DeviceController as vm">
<div>test</div><br>
<table>
<tbody>
<tr ng-repeat="device in vm.devices">
<td>{{device.Aid}}</td>
<td>{{device.DeviceId}}</td>
</tr>
</tbody>
</table>
</div>
</body>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.8/angular.min.js"></script>
<!--<script src="~/Scripts/angular.min.js"></script>-->
<script src="./app/app.module.js"></script>
<script src="./app/device.controller.js"></script>
</html>
NO IDEA why doesn't just display on the web page!
As you have data inside Devices object of response, then you need to change your assignment in ajax resolve like below.
vm.devices = result.data.Devices;
I'd suggest you to change your response from server, instead of sending Devices collection in Devices object, directly send it in response.
OR you could also make changes on HTML directly, but it wouldn't be good way to go.
<tr ng-repeat="device in vm.devices.Devices">
<td>{{device.Aid}}</td>
<td>{{device.DeviceId}}</td>
</tr>
my question is about a code combining HTML5 features ContentEditable and localStorage.
Here is my two JS function, one for storing the user edit in the table cell, another for getting the value and pass it to the table cell.
<script type="text/javascript">
function storeUserEdit(id) {
var pre_value = document.getElementById(id).innerHTML;
localStorage.setItem("userEdit",pre_value);
}
function applyUserEdit() {
if (localStorage.getItem("userEdit")){
var new_value = localStorage.getItem("userEdit");
}
document.getElementById('prjSch_row1_col1').innerHTML = localStorage.getItem("userEdit");
}
</script>
and here these two functions embedded in body content:
...
<td id="prjSch_row1_col1" contenteditable="true" onkeyup="storeUserEdit(this.id)" >
</td>
<script>applyUserEdit()</script>
...
I want to use this to many table cells in my HTML page and how I can replace prjSch_row1_col1 with id and pass it to function getUserEdit();
thanks a lot!
Are you trying to do something like this. because what you mention in the question is not enough to me to think about an answer. When do you need to fire applyUserEdit() function, on page load or ...
Please let me know enough details.
16/08/2013 >
Very sorry for the delay! Please find the below code which I tested in Firefox. Is this the behavior you want. Please don't test in fiddler. It's not working there, I don't know why.
`
<head>
<script type="text/javascript">
function storeUserEdit(id) {
var pre_value = document.getElementById(id).innerHTML;
localStorage.setItem("userEdit",pre_value);
localStorage.setItem('userEditControl', id);
}
function applyUserEdit(id) {
var new_value = '';
if (localStorage.getItem("userEdit")){
new_value = localStorage.getItem("userEdit");
}
if(localStorage.getItem('userEditControl') === id){
document.getElementById(id).innerHTML = localStorage.getItem("userEdit");
}
//this is just to check whether the code is working
document.getElementById('log').value = document.getElementById('log').value + '\n' + localStorage.getItem("userEdit");
}
</script>
</head>
<body>
<table border="1">
<tr>
<td>User Name:</td>
<td id="uname" contenteditable="true" onkeyup="storeUserEdit(this.id)" onblur="applyUserEdit(this.id)">value...</td>
</tr>
<tr>
<td>Password:</td>
<td id="pword" contenteditable="true" onkeyup="storeUserEdit(this.id)" onblur="applyUserEdit(this.id)">value...</td>
</tr>
</table>
<textarea multiline="true" id="log"></textarea>
</body>
`
Please let me know if you have any issues...