Load local array as Ajax file to improve performance - javascript

I am using DataTables to create a table, but it is loading awfully slow. I have approx. 9000 records that need to be processed from an SQL server (php is not an option). I am using XML and Spring MVC. I am using an XML and Java to gather the data and put it into a HashSet (i have tried lists also, neither seem faster than the other).
Once I get into JS I am using a for loop to populate my arrays, then I am using that as the "data" for the data tables. My understanding is that using serverSide and "ajax" (in place of data) will speed things up significantly so I was wondering if there was a way to take my arrays and use them as AJAX.
Thanks.
Current code:
var InternationalSet = [];
var storeIndex = 0;
<c:forEach items="${InternationalList}" var="entry">
InternationalSet[storeIndex]= ['', "${entry.getStoreId()}","${entry.getOrderPhone()}","${entry.getAddress1()}","${entry.getCity()}","${entry.getState()}", "${entry.getZip()}", "${entry.getMgrName()}",
"${entry.getFranchiseeName()}", "${entry.getOrglvl6Descr()}","${entry.getCommDescr()}", "${entry.getOrglvl8Name()}", "${entry.getLatitude()}", "${entry.getLongitude()}"];
storeIndex++;
</c:forEach>
$('#dataTable').html( '<table cellpadding="0" cellspacing="0" border="0" style="width: 99%; color:black" class="display compact" id="tableOne"></table>' );
var table = $('#tableOne').DataTable( {
"dom": '<l<t>ip>',
"deferRender": true,
"lengthChange": false,
"data": InternationalSet,
"pageLength": 10,
"orderMulti": false,
"columns": [.....

This is not a complete answer, but a quick improvement is to populate your list as a single statement instead of 9000.
var InternationalSet = [
<c:forEach items="${InternationalList}" var="e" varStatus="status">
[ '',
"${e.getStoreId()}",
"${e.getOrderPhone()}",
"${e.getAddress1()}",
"${e.getCity()}",
"${e.getState()}",
"${e.getZip()}",
"${e.getMgrName()}",
"${e.getFranchiseeName()}",
"${e.getOrglvl6Descr()}",
"${e.getCommDescr()}",
"${e.getOrglvl8Name()}",
"${e.getLatitude()}",
"${e.getLongitude()}"
] <c:if test="${!status.last}">,</c:if>
</c:forEach>
];
You can remove some of the new lines from the above to compactify it a little. Minor changes to the script also builds a single JSON object which you can return in an AJAX response to populate the table.
{
"data": [
<c:forEach items="${InternationalList}" var="e" varStatus="status">
....
</c:forEach>
]
}
If you are returning the data in sections from the server, your response would be changed to
{
"draw": ${param.draw},
"recordsTotal": ${yourTotal},
"recordsFiltered": ${yourFiltered},
"data": [
<c:forEach items="${InternationalList}" var="e" varStatus="status"
begin="${param.start}" end="${param.start + param.length}" >
....
</c:forEach>
]
}
(You will have to add some range/value checking on the param values)

Related

render java script object on html page

I want to render data object in the body as a table with three columns
one for the key like "ASIANPAINT24JUN21FUT"and other two for the links
I don't have any experience with javascript, I tried using renderjson to render the
json object received, but it renders just plain text,
I want to render the object as a table, and the links in it should be clickable
How can I achieve this?
index.html
<body>
// render data object here
<script>
var eventSource = new EventSource("/listen")
eventSource.addEventListener("message", function(e) {
console.log(e.data)
}, false)
eventSource.addEventListener("online", function(e) {
let data = JSON.parse(e.data)
}, true)
</script>
</body>
data object
{
"ASIANPAINT24JUN21FUT": [
"https://in.tradingview.com/chart/?symbol=NSE:ASIANPAINT1!",
"https://kite.zerodha.com/chart/ext/tvc/NFO-OPT/ASIANPAINT21JUN2980CE/15044354"
],
"DEEPAKNTR24JUN21FUT": [
"https://in.tradingview.com/chart/?symbol=NSE:DEEPAKNTR1!",
"https://kite.zerodha.com/chart/ext/tvc/NFO-OPT/DEEPAKNTR21JUN1820CE/20372738"
],
"DRREDDY24JUN21FUT": [
"https://in.tradingview.com/chart/?symbol=NSE:DRREDDY1!",
"https://kite.zerodha.com/chart/ext/tvc/NFO-OPT/DRREDDY21JUN5350CE/20732162"
],
"ESCORTS24JUN21FUT": [
"https://in.tradingview.com/chart/?symbol=NSE:ESCORTS1!",
"https://kite.zerodha.com/chart/ext/tvc/NFO-OPT/ESCORTS21JUN1220CE/20892674"
]
}
You can use following code to display the data in HTML.
<body>
<div id="table-div"></div>
<script>
let data = {
"ASIANPAINT24JUN21FUT": [
"https://in.tradingview.com/chart/?symbol=NSE:ASIANPAINT1!",
"https://kite.zerodha.com/chart/ext/tvc/NFO-OPT/ASIANPAINT21JUN2980CE/15044354"
],
"DEEPAKNTR24JUN21FUT": [
"https://in.tradingview.com/chart/?symbol=NSE:DEEPAKNTR1!",
"https://kite.zerodha.com/chart/ext/tvc/NFO-OPT/DEEPAKNTR21JUN1820CE/20372738"
],
"DRREDDY24JUN21FUT": [
"https://in.tradingview.com/chart/?symbol=NSE:DRREDDY1!",
"https://kite.zerodha.com/chart/ext/tvc/NFO-OPT/DRREDDY21JUN5350CE/20732162"
],
"ESCORTS24JUN21FUT": [
"https://in.tradingview.com/chart/?symbol=NSE:ESCORTS1!",
"https://kite.zerodha.com/chart/ext/tvc/NFO-OPT/ESCORTS21JUN1220CE/20892674"
]
}
let tableDiv = document.getElementById("table-div");
let tableRows = "";
Object.keys(data).map(key => {
tableRows += `
<tr>
<td>${key}</td>
<td>${data[key][0]}</td>
<td>${data[key][1]}</td>
</tr>
`
})
tableDiv.innerHTML = `
<table>
<tr>
<th>Key</th>
<th>Link 1</th>
<th>Link 2</th>
</tr>
${tableRows}
</table>`
</script>
</body>
to do this you should modify the dom using javascript, here the documentation about html5 tables https://developer.mozilla.org/en-US/docs/Web/HTML/Element/table, about links https://developer.mozilla.org/en-US/docs/Web/HTML/Element/a, and i am pretty sure you will also need this https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/keys, using this and some kind of bucle like a foreach, a map or a for, you can access the object info in a dynamic way, also if you need it you have some documentation about dom manipulation https://developer.mozilla.org/en-US/docs/Web/API/Document_Object_Model/Introduction, maybe you also find useful methods like document.getElementById

Customizing DataTables with WEB API OData service for filtering EF - column search not working

I am using DataTables on the client side and ASP.NET WEB API OData queryable service on the server side. The issue with sorting and filtering DataTable columns on the server side is that DataTables are generating that awful super long request with all columns info, even when they are not used for sorting or filtering. I've decided to write custom AJAX call from client to server to create neat odata query, that can be applied easily to EF context. Unfortunately column searching fields have stopped rendering as a inputs. What can be the issue?
JavaScript and HTML code:
$(document).ready(function() {
var options = new Object();
options.searching = true;
options.searchable = true;
options.aoColumns = [{
"sName": "USER_NAME",
"searchable": true
}];
options.bProcessing = true;
options.bServerSide = true;
options.sAjaxSource = "http://localhost/api/list";
options.fnServerData = function(sSource, aoData, fnCallback) {
var filter = "$top=5"; //just as example
$.getJSON(sSource, filter, function(json) {
fnCallback(json);
});
}
$('#myTable').dataTable(options);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="//cdn.datatables.net/1.10.7/js/jquery.dataTables.min.js"></script>
<table id="myTable" class="table">
<thead>
<tr>
<th>
First Name
</th>
...
</tr>
</thead>
<tfoot>
<tr>
<th>
First Name
</th>
...
</tr>
</tfoot>
</table>
The service works fine, and looks like this (I've made this code as easy to understand as possible).
C# code:
public HttpResponseMessage List(ODataQueryOptions<User> options)
{
var result = oDataQueryOptions.ApplyTo(_context.Users) as IEnumerable<User>;
JQueryJsonResponse jsonUserResult = new JQueryJsonResponse
{
Draw = xxx,
iTotalRecords = xxx,
iTotalDisplayRecords = xxx,
aaData = result.ToList()
};
return Request.CreateResponse(HttpStatusCode.OK, jsonUserResult);
}
I would expect something like this:
But I get this:
CAUSE
You have server-side processing mode enabled with options.bServerSide = true;. In server-side processing mode filtering, paging and sorting calculations are all performed by a server.
SOLUTION
You need to handle parameters sent by the client on the server and perform filtering, paging and sorting. See full list of parameters sent in server-side processing mode.
Alternative solution is to disable server-side processing mode with options.bServerSide = false; and let DataTables perform filtering, paging and sorting on the client side.
OK, the question is not well formed, sorry. What I meant, that I want to apply column search to my datatables. During the copy-paste phase from other table I just missed some lines of code.
I've added something like this, and now it's working!
// Setup 'Search'
var filterSelector = '#myTable' + ' tfoot th';
$(filterSelector).each(function() {
var searchbox = $(this);
searchbox.html('<input type="text" class="form-control" placeholder="Search" />');
});
//Apply DataTables
var table = $('#myTable').DataTable(options);
$('.dataTables_filter input').attr("placeholder", "Search");
// Apply generic search
table.columns().every(function() {
var that = this;
var thatFooter = $('input', this.footer());
thatFooter.on('keyup change', function() {
that.search(this.value).draw();
});
});

Datatables TypeError: c is undefined

I try to use jQuery DataTables but I get the error
TypeError: c is undefined
I don't know what is wrong with my code as I can see the JSON correctly retrieve and is in the correct format too but I don't know what is wrong with it that I get the above error.
My JSON :
{"Data":[{"LOGIN":10184},{"LOGIN":10214},{"LOGIN":10180},{"LOGIN":10187},{"LOGIN":10179},{"LOGIN":10280},{"LOGIN":201},{"LOGIN":10238},{"LOGIN":10296},{"LOGIN":10312}]}
and my DataTables code:
$(document).ready(function() {
$('#tablename').dataTable( {
"processing": true,
"serverSide": true,
"ajax": {
"type": "POST",
"url": "https://test.com/api/db/select",
"data": function ( json ) { return JSON.stringify( { "Sql": 12 } );},
"contentType": "application/json; charset=utf-8",
"dataType": "json",
"processData": true,
beforeSend : function(xhr){
var access_token = sessionStorage.getItem('access_token');
xhr.setRequestHeader('Authorization', 'Bearer ' + access_token);
}
},
"dataSrc": "Data",
"columns": [
{ "data": "LOGIN" }
]
} );
} );
Check whether you have added
<thead></thead>
<tbody></tbody>
I've resolved this problem by adding those.
So basically the structure must be like:
<table>
<thead>
<tr>
<th></th>
<th></th>
</tr>
</thead>
<tbody>
<tr>
<td></td>
<td></td>
</tr>
</tbody>
</table>
Sometime, This type issue arrives by fixing mismatched / unequal columns with HTML and datatables columns.
"columns": [
null,
null,
null,
{"orderable": false, "width":"2%"},
],
Above javascript defined 4 columns and HTML having 5 columns
<tr>
<td>A</td>
<td>B</td>
<td>C</td>
<td>D</td>
<td>E</td>
</tr>
Hence you will have to fix / equal both side HTMl and Datatable configuration.
"columns": [
null,
null,
null,
null, //Added New
{"orderable": false, "width":"2%"},
],
dataSrc is a special dataTables ajax option, that should be included inside the ajax object :
"ajax": {
"dataSrc": "Data", //<--- place dataSrc here instead
"type": "POST",
...
}
You have placed it outside ajax, and by that dataTables have no idea what source to use (besides blindly trying the ajax response) or where LOGIN belongs.
in my case, i had to remove colspan attribute from a th inside thead and get rid of the error ;(
In my case, missing aaData in sever side return result.
//Javascript
$('#table').DataTable({
sAjaxSource: '/load',
aoColumns: [
...
],
});
//server side(in Rails)
render json: {'aaData'=>data}
In my case, I got the same error because I used the ajax.dataSrc( data ) function to manipulate the data. But after that i forgot to return the data.
"dataSrc": function ( json ) {
for ( var i=0, ien=json.data.length ; i<ien ; i++ ) {
//somethings...
}
return json.data;// I forgot this line, then i got the error "TypeError: c is undefined"
}
After a few minutes, I checked the documentation of the ajax.dataSrc function and I noticed that I did not have the return:
Returns: array. Array of data that DataTables is to use to draw the table
I hope you do not have the same distraction...
In my case th and td , count is not equal due do colspan, removed colspan and it worked.
In my case, my front-end: ajax: { dataSrc: "data" } was OK, but on server-side I returned object where first letter was Upper return Json(new { Data = model });
Another day, another solution - this time caused by a style sheet!
After spending hours reducing a gigantic web page to the raw charts code, I found that this error shows (for pie charts) when CSS rules for fonts in the stylesheet contain the calc function.
In our style sheet, this line of code:
html {
font-size: calc(12px + 5%);
}
...broke the chart. We needed this because our webfont wasn't resizing smoothly and needed a size slightly larger than 12px but smaller than 13px, and this trick forced a better resize.
Overwriting the style rule on the chart widget directly solved the issue:
CSS
html {
font-size: calc(12px + 5%);
}
.widget {
font-size: 12px /* Replace the above rule */;
}
JS
var GoogleChart1 = new google.visualization.PieChart(document.getElementById('Chart1'));
HTML
<div id="Chart1" class="widget"></div>
check followings
<td></td> -- check count
<th></th> -- check count
check <tbody> and <thead> - opening and closing
In my case the number of column in <thead> tag is different than the number of column in <tbody> tag.

Fill jQuery DataTables with drop down and PHP

I'm working with DataTables and this is my scenario:
1)I've got a drop down menu with some user's name and their proper ID;
2)I've got an empty DataTable;
3)I would like to detect user's ID selecting one row from drop drown menu, pass it to server_processing.php(DB query) using data: property of DataTables and display DB query's result back in Data Table.
Code for drop down:
<select id="selezione_user" name="selezione_user" class="select2 form-control">
<option value="">Seleziona</option>
<?php $query=mysql_query("SELECT user_id,nome FROM user ORDER BY nome",$conn);
while($row=mysql_fetch_array($query)){
echo "<option value='$row[user_id]'>$row[nome]</option>";
}?>
</select>
Code for DataTable (HTML):
<table class="table table-striped" id="prova">
<thead>
<tr>
<th>User</th>
<th>Comune</th>
<th>Mail</th>
<th>Stato</th>
</tr>
</thead>
<tbody>
</tbody>
</table>
Code for DataTable (JS)
$(document).ready(function() {
var oTable = $('#prova').dataTable( {
"processing": true,
"serverSide": true,
"ajax": {
"url": "scripts/server_processing.php",
"data": {
"user_id": null //set to show empty DataTable
}
},
});
$('#selezione_user').change(function() {
aoData.push({
"user_id": this.value
})
});
});
But the code above doesn't work and this problem is driving me crazy, I hope someone will help me.
Thanks to all.
Giacomo.
EDIT
I solved my problem using removing data: and changing DataTables(JQuery) function in this way:
$('#selezione_centri').change(function() {
var valore = this.value;
var string = ('scripts/server_processing.php?id_professionista='+valore);
table.ajax.url(string).load();
table.reload();
});
I think you should check the row
echo "<option value='$row[user_id]'>$row[nome]</option>";
Try changing it to
echo "<option value='".$row["user_id"]."'>".$row["nome"]."</option>";
This is somewhat explained here: Accessing arrays whitout quoting the key , the php array keys need to be quoted. This is merely a longshot here!
For more precise debugging (if this is not enough), you should provide the php code.

Specify column data type with a <th> attribute for DataTables

We're using the DataTables jQuery plugin (http://www.datatables.net) to create sortable tables. This plugin auto-detects the data type of the data in each column.
When you want to specify the data type of a column yourself, you add the "aoColumns" attribute when you initialize the datatable:
$('#accountTable').dataTable({
"bPaginate": false,
"sScrollX": "100%",
"bScrollCollapse": true,
"aoColumns": [
null,
null,
{ "sType": "currency" },
{ "sType": "currency" }
]
});
Note, I downloaded the currency data type plugin for datatables. This works great.
However, I'm concerned that if we ever make changes to the table column, we'll forget to go back into the JS and change how the datatables plugin is initialized on that table.
So... It would be ideal to specify the data types directly in the table as necessary:
<table class="dataTables display">
<thead>
<tr>
<th>Category</th>
<th>Product</th>
<th sType="currency">Cost</th>
<th sType="currency">Retail</th>
...
Is there any way to do this, either with default functionality of DataTables (which I can't find) or using a JS loop or something to loop through the tags of the table and update the sType where "sType" attribute exists?
Here is an absolutely cool way to do it:
Your header HTML:
<table id="sorted-table">
<thead>
<tr>
<th data-s-type="string">Number</th>
<th data-s-type="html">Complex Name</th>
<th>Price</th>
<th data-b-sortable="false">Action</th>
</tr>
</thead>
...
Your JS:
$('#sorted-table').dataTable({
...
"aoColumns": $('#sorted-table').find('thead tr th').map(function(){return $(this).data()})
});
Note: those dashes in data attributes are needed. They get converted to camelCase form by jQuery which makes it compatible with the data tables API.
Picking up on CBroe's comment, this is exactly what I do. Just ensure that your custom attributes are prefixed with data-, such as data-stype='currency' per the HTML specs.
Having your JS loop through and check for attributes on the headers would work, but you can't just invent an sType attribute and have it show up in the DOM. You'd have to subvert a valid but unused attribute like headers (and that might cause trouble for screen readers; there may be a better option).
Edit:
OK, having read CBroe's comment, I guess it is possible to give an element an arbitrary attribute.
So, if you wanted to be HTML5 compliant, you could name the property data-sType and then do something like this:
var aoColumns = [];
$('#accountTable > th').each(function() {
var sType = $(this).getAttribute("data-sType");
aoColumns.push(sType ? sType : null);
});
$('#accountTable').dataTable({
...
"aoColumns": aoColumns
});
Thanks to all for your help! I had to make a couple tweaks to Russell Zahniser's comment for it to work for me:
Changed $('#accountTable > th') to $('#accountTable thead th')
Changed aoColumns.push(sType ? sType : null) to aoColumns.push(sType ? { "sType" : "currency" } : null)
End result:
var aoColumns = [];
$('#accountTable thead th').each(function() {
var sType = $(this).getAttribute("data-sType");
aoColumns.push(sType ? { "sType" : "currency" } : null);
});
$('#accountTable').dataTable({
...
"aoColumns": aoColumns
});

Categories

Resources