Background information: I'm retrieving an XML file every minute, parsing it, and appending the contents to an html table.
Here's the setInterval function
setInterval(function(){
data.length = 0;
deleteRows();
ajaxGet('rest/room/wakeup/?type=pending', parsePending);
appendAll();
console.log("refreshed");
}, 60000);
Data is an array of arrays. Each sub array contains a row of the table I'd like to append. Data is declared globally.
ajaxGet retrieves the XML file and calls the parsing function to process and pushes each row array into the data array. The parsing function logs each row to the console so I know it's working correctly.
Now here's where things go wrong.
function appendAll(){
for (var i = 0; i < data.length; i++){
var row = "<tr>";
console.log("row appended");
for (var key in data[i]){
row = row + "<td>" + data[i][key] + "</td>";
console.log("appended" + data[i][key]);
}
row = row + "</tr>";
$("#pending_wakeups tbody").append(row);
}
console.log("appended");
}
If any function within setInterval clears data before appendAll(), data.length will return 0. Despite the parsing function returning a full array to the console one call before appendAll(), it refuses to work for me.
Related
I m using AdminBSB Material design Admin panel for a project. Im getting JSON data from an API and displaying it on a DataTable . The Data showing in the table but when i click any function sorting/searching all the data disappear from the table and showing 0 data
dataType: 'json',
type: "GET",
success: function (data) {
$('#loading-data3').hide();
var i = 0;
var count = data.total;
console.log(count);
for (i = 0; i <= count; i++) {
$('#remaining-time').find('tbody').append(
"<tr><td>" + data.data[i].ASSIGNEE + "</td><td>" +
data.data[i].totalEstimateTime + "</td><td>" +
data.data[i].timeSpent + "</td><td>" +
data.data[i].remainTime + "</td></tr>"
);
}
}
});
sample screenshot
You are using DataTables... This plugin create some new elements dynamically on every draw (caused by ordering, searches, pagination, etc). If you want to add a new row to a Datatable already instantiated, you have to use the row.add() method.
You should have the DataTable instantiation somewhere in your code, possibly with an option object passed as argument. If you do not yet, assign a variable to the instance.
var myTable = $('#remaining-time').DataTable();
Then when you loop through your json data to add rows, it should look like this:
// Your loop through json
var count = data.total;
console.log(count);
for (i = 0; i <= count; i++) {
myTable.row.add([ // "myTable" refers to the Datable instance here.
data.data[i].ASSIGNEE,
data.data[i].totalEstimateTime,
data.data[i].timeSpent,
data.data[i].remainTime,
]);
}
Documentation
So, am currently trying to pull out two different array values from arrays chanArrId & chanArrName via express(socket.io) & node.js.
Then once I have those display them in a table on the same row E:G
<tr class="exe">
<td>SIP/487-00000060</td>
<td>0000000001</td>
</tr>
<tr class="exe">
<td>SIP/488-00000060</td>
<td>0000000002</td>
</tr>
Then for the next set take a new row, do the same for the following channel values.
When I add another pull the next two out without repeating itself. I have had some kind of success but always fall just short, with wrong positioning or duplicated values.
I have it working fine with one value but not both so:
Call extension 488: Add Channel name and value to the page from array etc.
Works for the first one it works fine as seen at the top it works grand then I get the following when I add a second pair of values:
<tr class="exe" id="exe">
<td>SIP/487-00000060</td>
<td>1445964898.228</td>
<td>1445964898.2281445964900.229</td>
</tr>
It skips the SIP name and then just adds two channel ids in the next row.
Below is the latest code have been tweaking, to see what ave been trying to accomplish.
Client side
socket.on('sipname', function (data,datad) {
var sipname = '';
var sipid = '';
$(".exe").remove();
for (i = 0; i < data.length; i++) {
sipname += data[i];
if (sipname) {
$sipname.append('<tr class="exe" id="exe">\
<td id="siptd">' + sipname + '</td>');
}
for (i = 0; i < datad.length; i++) {
sipid += datad[i];
if (sipid) {
$('#sipTable td:last').after('<td>' + sipid + '</td></tr>');
}
}
sipid = '';
}
});
Server side function
function updateSip() {
io.sockets.emit('sipname', chanArrName,chanArrId);
chandump();
}
Stasis: Where am pushing values into array
bridge.addChannel({
channel : channel.id
}, function (err) {
var name = chanArrName.push(channel.name)
var id = chanArrId.push(channel.id)
updateSip();
if (err) {
throw err;
}
Hope you guys can give me a little bit of guidance.
In the client code you have a nested for-loop with the same index variable as the outer loop, which means the outer one will not run as many times as expected.
Also, the += operator will concatenate new values to previous values, explaining the concatenated channel ids you notice. You are already expanding the DOM with nodes incrementally, so there is no need to use +=. Just assign. The same holds for the outer loop: just assign to sipname with =.
Indenting your code correctly may also help debugging it.
Finally, declare your index variable(s) with var.
With these corrections, you get this:
socket.on('sipname', function (data, datad) {
var sipname, sipid, dataHtml;
$(".exe").remove();
for (var i = 0; i < data.length; i++) {
sipname = data[i];
if (sipname) {
dataHtml = '<td id="siptd">' + sipname + '</td>';
for (var j = 0; j < datad.length; j++) {
sipid = datad[j];
if (sipid) {
dataHtml += '<td>' + sipid + '</td>';
}
}
$sipname.append('<tr class="exe" id="exe">' + dataHtml + '</tr>');
}
}
});
EDIT:
Above code was updated after comments. This version concatenates the HTML for each TD in a variable, to then finally wrap it in a TR tag and append it to $sipname. I have no view on the variable $sipname, so I assume it is set correctly.
There is one thing you certainly need to fix:
The code sets values for the id properties of the generated nodes, but always the same ones. This is not acceptable in HTML: an id should be unique in the document.
This is how I managed to tackle it in the end:
socket.on('sipname', function (data, datad) {
var sipname = '';
var sipid = '';
$('.exe').remove();
for (var i = 0; i < data.length; i++) {
sipname = data[i];
sipid = datad[i];
if (sipname) {
$sip.html('<tr class="exe">\
<td class="sipid">' + sipid + '</td>\
<td class="sipname">' + sipname + '</td>\
<td><button class="btn btn-default mute" id="mute" type="submit"><span>Mute</span></button></td>\
<td><button class="btn btn-default kick" id="kick" type="submit">Kick</button></td>\
</tr>');
}
}
});
Because am handling the two arrays at the same time on the server side and how there are both directly related every time I pull them out into the web page I simply E.G Channel.name & Channel.id
I just started calling out the value along with sipname as they will both have the same set of values every time and also get added or removed at the same time.
Hope this makes sense.
This is how I got it to work in the end for those who want an alternate solution.
Does anybody know how to convert my data to table by using Javascript or JQuery, I got this data for example:
var data1 = ["1","3","5"]
var data2 = ["a","b","c"]
Once the data1 and data2 value is updated then the rows and columns are also automatic updated.
result:
etc:
No. Alphabet
1 a
3 b
5 c
In your .html file
<table class="myTable"></table>
In your .js file
function generateTable(data1, data2){
var $table = $('.myTable');
for (var i = 0; i < data1.length; i++){
var $aSingleContent = '<tr><td>'+data1[i]+'</td><td>'+data2[i]+'</td></tr>';
$table.append($aSingleContent);
}
}
function modifyData() {
var data1 = ["1","3","5"];
var data2 = ["a","b","c"];
generateTable(data1, data2);
}
--------------------------------Update-------
I put the code in jsfiddle
http://jsfiddle.net/ronansmith/daLf9t85/
remember to add External Resources of jQuery
I like the idea of creating a function to dynamically set the innerHTML of a div, propagating it with a table.
It should look something like this:
function generate_table(array1, array2) {
var html = '<table>';
// cycles through all the elements in the array
for (var i = 0; i < array1.length; i++) {
html += '<tr><td>' + array1[i] + '</td><td>' + array2[i] + '</td></tr>';
}
html += '</table>';
// places the table in the element
document.getElementById('content').innerHTML = html;
}
generate_table() takes in the two arrays and constructs a String, propagating it with the contents of the array in a for loop. Then it gets a div named content and sets its innerHTML to create the table.
In your webpage, be sure to include the div to which the table will be inserted:
<div id="content"></div>
You can also call generate_table() every time your array refreshes, and the table will update.
I hope this helps you!
there are two ways you can do this. one, you wrap a function/class around your data and have a "changedata" method that changes the data and updates the html or you have a setInterval that listens for changes to those variables and serves the changes to you markup. the former is much better than the latter in my opinion
Which way will be faster and use less memory?
For now i have rendered dynamic <table> by jQuery. Sometimes it has around few thousand cells and it is working so slowly when i do events on it. Html2Canvas is taking alot time to render this table as image. So i wonder about use interactive canvas.
Here is fiddle with script for generating table http://fiddle.jshell.net/j6G66/
I created two examples,
One that mirrors the way you're creating your table
and that's by creating and appending jQuery object elements on every loop iteration:
function createDynamicTable(rows, cols) {
var table = $('<table />');
for(var i=0; i<rows; i++){ // noprotect
var row = $('<tr />');
for(var j=0; j<cols; j++){
var cell = $('<td />');
cell.text("R"+i+"-C"+j);
cell.appendTo( row ); // Appends here....
}
row.appendTo( table ); // Appends here....
}
$('#tableContainer').append( table ); // Appends here....
}
The second one uses a different way of creating a table, that is based instead on the principle of
concatenating a HTML String representation of the needed elements:
function createDynamicTable(rows, cols) {
var table = "<table>";
for(var i=0; i<rows; i++){
var row = "<tr>";
for(var j=0; j<cols; j++){
var cell = "<td>R"+i+"-C"+j+"</td>";
row += cell;
}
row += "</tr>";
table += row;
}
table += "</table>"
$('#tableContainer').append( table ); // Append only once!
}
Now let's be humans and exaggerate a bit creating a table with 1000 rows and 10 cells in each running:
var start = new Date().getTime();
createDynamicTable(1000, 10);
var total = new Date().getTime() - start;
And let's see the results:
IN-LOOP jQuery OBJECTS/EL. CREATION vs. IN-LOOP STRING CONCATENATION
~920 ms ~130 ms
jsBin demo 1 jsBin demo 2
A (logical) side-note on the string concatenation:
you'll not be able to keep copies of alive Objects inside data-* attributes like i.e:
cell = "<td data-objectcopy='"+ myObject +"'>...</td>"
cause the object will result in String "[object Object]", in contrast to jQuery's .data():
cell = $("<td />", {html:"..."}).data("objectcopy", myObject );
where any further change to the object like: $(td).eq(0).data().objectcopy.someProperty = "new value"; will keep it's reference to the original myObject object alive.
I have an array with a variable amount of records. And I want to print every record of the array in the same html page. I prefer it to display in a list.
I have the following code. However this does only print the last record of the array because it overwrites the previous record in my html ul-element.
for (var i = 0; i < feedbackGeenLid.length; i++)
{
document.getElementById("feedback").innerHTML= ("<li>"+feedbackGeenLid[i] + "</li>");
}
Does anyone have an idea on how to realize this?
Your code keeps replacing the innerHTML you need to add to it.
document.getElementById("feedback").innerHTML += ("<li>"+feedbackGeenLid[i] + "</li>");
^
|
Added + here
For better performance build one string and set it to innerHTML at the end of the loop.
var out = "";
for (var i = 0; i < feedbackGeenLid.length; i++)
{
out += "<li>"+feedbackGeenLid[i] + "</li>";
}
document.getElementById("feedback").innerHTML= out;
Another option, use appendChild()
you are rewriting the content in each loop. use a variable to concatenate the content and then put it in the element:
var html = '';
for (var i = 0; i < feedbackGeenLid.length; i++)
{
html += "<li>"+feedbackGeenLid[i] + "</li>";
}
document.getElementById("feedback").innerHTML= html;