html rendering time improvement with jquery datatable - javascript
I had implemented datatable with almost 3000 row of data and it was taking like 4 to 5 seconds to render the HTML by this code:
$('#book_table').html(book_table);
$('#book_table > table').DataTable({...data table initializing});
when I was trying to improve rendering time I tried to hide the HTML data container element (display: none) then show it after datatable initializing and the result was shocked it took just 200 ms for rendering by this code
$('#book_table').addClass('hidden');
$('#book_table').html(book_table);
$('#book_table > table').DataTable({...data table initializing});
$('#book_table').removeClass('hidden');
the question is : how could hiding the data container and showing it after datatable initializing could improve the rendering time from 4 seconds to 200 ms?
Related
Qualtrics display logic interferes with javascript .hide()
I have a side-by-side question in Qualtrics with 30 rows. Each of the first 20 rows has display logic such that they only appear when something is entered in text boxes in prior questions. Each of the last 10 rows has display logic such that at least 10 rows show up in the entire question, i.e. row 21 only shows up if none of the first 20 are displayed, row 22 shows up if only one of the first 20 are displayed... row 30 shows up if 9 of the first rows are displayed, and none of them appear if at least 10 of the first rows are displayed. The first column of the question is a checkbox, and I'm using the following Javascript to hide the checkboxes for the last 10 rows: Qualtrics.SurveyEngine.addOnload(function() { var qid = this.questionId; var p = $(qid); p.down('label[for="QR~'+qid+'#1~21~1"]').hide(); p.down('label[for="QR~'+qid+'#1~22~1"]').hide(); p.down('label[for="QR~'+qid+'#1~23~1"]').hide(); p.down('label[for="QR~'+qid+'#1~24~1"]').hide(); p.down('label[for="QR~'+qid+'#1~25~1"]').hide(); p.down('label[for="QR~'+qid+'#1~26~1"]').hide(); p.down('label[for="QR~'+qid+'#1~27~1"]').hide(); p.down('label[for="QR~'+qid+'#1~28~1"]').hide(); p.down('label[for="QR~'+qid+'#1~29~1"]').hide(); p.down('label[for="QR~'+qid+'#1~30~1"]').hide(); }); It works fine if none of the previous rows are displayed: But bombs if even one of the previous rows is displayed: I poked around with Inspect Element on the preview to see if the tags changed somehow, but couldn't find anything unexpected as far as changing IDs. When checking the element for the checkbox on row 23 when none of the first 20 rows appear: <input id="QR~QID4#1~23~1" name="QR~QID4#1~23~1" value="Selected" data-runtime-checked="runtime.Children.1.Choices.23.Answers.1.Selected" aria-labelledby="question1QID4 question1QID4-answer1QID4 choice23QID4" class="QWatchTimer" type="checkbox"> <label for="QR~QID4#1~23~1" class="q-checkbox" data-runtime-class -q-checked="runtime.Children.1.Choices.23.Answers.1.Selected" style="display: none;"></label> As expected, the label code is grayed out. When one of the first 20 rows appears, it's much the same, but style="display: none;" does not appear at the end: <input id="QR~QID4#1~23~1" name="QR~QID4#1~23~1" value="Selected" data-runtime-checked="runtime.Children.1.Choices.23.Answers.1.Selected" aria-labelledby="question1QID4 question1QID4-answer1QID4 choice23QID4" class="QWatchTimer" type="checkbox"> <label for="QR~QID4#1~23~1" class="q-checkbox" data-runtime-class -q-checked="runtime.Children.1.Choices.23.Answers.1.Selected"></label> I'm at a loss for how activation of display logic would interfere with the Javascript.
After a few hours of percolating, I remembered that if a display logic hides an item with Javascript, that script won't run. I hadn't realized that it's not just on a line-by line basis - looks like if one element controlled by one line of code gets hidden, the whole block of code gets invalidated. I was able to solve it with a loop that dynamically considered only the rows that would be displayed: Qualtrics.SurveyEngine.addOnload(function() { //Remove checkboxes for last ten options var qid = this.questionId; var p = $(qid); var count = Qualtrics.SurveyEngine.getEmbeddedData('count'); var min = 21+count; for (var i = min; i < 31; i++) { p.down('label[for="QR~'+qid+'#1~'+i+'~1"]').hide(); } }); At least in my case, the count variable was used to determine how many of the last 10 rows to display. Once I built that into the parameters for the loop, nothing would be invalidated by the display logic. (Check here for the process on that if interested.) Lesson learned: I should've been using a loop to begin with - modifying the parameters is an easy step after that.
Datatables: Remove row without affecting "(filtered from X total entries)"
I have a reasonably large table which when run through the Datatables API takes a couple of seconds to render. While it's rendering I have the opacity of all the rows set to 0 with an additional row at the beginning containing a note that reads "Rendering table..." so there's less juttering and ugly tables on display till it's ready to be seen. Using the initComplete callback function this row is then deleted and the other rows made visible: "initComplete": function(){ $( 'table.MIS_return_data tbody.MIS_returned_content tr.render-note' ).remove(); $( 'table.MIS_return_data tbody.MIS_returned_content tr:not(.no-select)' ).css('opacity', 1); $( 'table.MIS_return_data tbody.MIS_returned_content tr.no-select' ).css('opacity', 0.6); }, The problem with this is that at the bottom of the table I get a note: Showing 1 to 580 of 580 entries (filtered from 581 total entries) That 1 entry that it has filtered is the row with the rendering note. I need the row completely removed and no longer "seen" by the API. How can I do this? I have tried using the following as well instead of the jQuery.remove(): "initComplete": function(){ table.rows( $( 'table.MIS_return_data tbody.MIS_returned_content tr.render-note' ) ).remove(); table.draw(); $( 'table.MIS_return_data tbody.MIS_returned_content tr:not(.no-select)' ).css('opacity', 1); $( 'table.MIS_return_data tbody.MIS_returned_content tr.no-select' ).css('opacity', 0.6); }, But not only does this not work, uniquely it also only applies the opacity to the first row in the table. One workaround is the remove the note at the bottom completely using: "language": { "infoFiltered": "", }, However, this is not ideal as I would like for users to be able to filter the results, hiding/displaying rows by certain parameters. That note therefore will have a practical use. If you need any more details or clarification on what's written please ask. Any help is appreciated! Thanks
Like #annoyingmouse said above.. Inject over the table a "block" that represents the table... once the javascript has finished building the table.. hide the block and show the table either with a crude hide/show or using CSS fade transitions on the parent. This way it is a better separation of concerns... the datatable does its thing with correct data, the ui does its thing by showing and hiding at the right time. This is a the same strategy that other sites such as linkedin and facebook use. On initial load the page renders a static block (on the fb wall for example this block looks like a faded out wall post)... then once the xhr request has returned with data the frontend app replaces the static block with actual content. In your case it would be the same, but instead of waiting for an xhr to resolve it would be triggered by the datatables render callback.
ui-grid has duplicate rows
I don't know how this started happening but a ui-grid (project home) on my page (angular SPA) is duplicating 2 rows somehow (and I don't want it to). Refreshing the page (Chrome) has no effect (I have devtools open, with Disable cache checked). For reference: I am setting the grid.data to an array with 65 entities, so that count is correct, and if I remove all filters it shows all 65, but actually 67 rows shown (I took the time to count, with the interesting find that alternating rows don't necessarily keep their grey or white color as you scroll up and down). Here's what I am seeing. If I click row 3 or 4, both are selected and 1 and 2 are unselected. I assume that they have the same generated Id. Note here that it does say that only one row is selected, but 4 are shown! I can open the page in Firefox and log in, then go to this page which then looks right, so it is either something in Chrome or something in this instance and other users wouldn't see it. Here is the array from the grid.data: [{"Name":"Trainer","Desc":"","Type":"string","OptionsCount":6,"$$hashKey":"uiGrid-000W"}, {"Name":"System","Desc":"Practice","Type":"string","OptionsCount":97,"$$hashKey":"uiGrid-000Y"}, {"Name":"EMR","Desc":"Electronic","Type":"string","OptionsCount":67,"$$hashKey":"uiGrid-0010"}, {"Name":"Guideline","Desc":"Guideline","Type":"string","OptionsCount":7,"$$hashKey":"uiGrid-0012"}, {"Name":"Notes","Desc":"Notes","Type":"string","OptionsCount":4,"$$hashKey":"uiGrid-0014"}, {"Name":"Scorecard","Desc":"April 2015","Type":"string","OptionsCount":27,"$$hashKey":"uiGrid-0016"}, {"Name":"Scorecard","Desc":"July 2015 ","Type":"string","OptionsCount":27,"$$hashKey":"uiGrid-0018"}, {"Name":"Scorecard","Desc":"November 2","Type":"string","OptionsCount":27,"$$hashKey":"uiGrid-001A"}, {"Name":"Scorecard","Desc":"December 2","Type":"string","OptionsCount":27,"$$hashKey":"uiGrid-001C"}, {"Name":"Scorecard","Desc":"September ","Type":"string","OptionsCount":27,"$$hashKey":"uiGrid-001E"}, {"Name":"2012","Desc":"","Type":"money","$$hashKey":"uiGrid-001G"}, {"Name":"2014","Desc":"","Type":"money","$$hashKey":"uiGrid-001I"}, {"Name":"2015","Desc":"","Type":"money","$$hashKey":"uiGrid-001K"}, {"Name":"2016","Desc":"","Type":"money","$$hashKey":"uiGrid-001M"}, {"Name":"2017","Desc":"","Type":"money","$$hashKey":"uiGrid-001O"}, {"Name":"Specialty","Desc":"Primary","Type":"string","OptionsCount":191,"$$hashKey":"uiGrid-001Q"}, {"Name":"Specialty2","Desc":"Secondary","Type":"string","OptionsCount":191,"$$hashKey":"uiGrid-001S"}, {"Name":"Special","Desc":"Special","Type":"string","$$hashKey":"uiGrid-001U"}, {"Name":"Rooming In","Desc":"Rooming in","Type":"date","$$hashKey":"uiGrid-001W"}, {"Name":"HTN","Desc":"Hyper","Type":"date","$$hashKey":"uiGrid-001Y"}, {"Name":"Depression","Desc":"Depression","Type":"date","$$hashKey":"uiGrid-0020"}, {"Name":"Measure","Desc":"measure","Type":"date","$$hashKey":"uiGrid-0022"}, {"Name":"HCC","Desc":"HCC","Type":"date","$$hashKey":"uiGrid-0024"}, {"Name":"Data 1","Desc":"First","Type":"date","$$hashKey":"uiGrid-0026"}, {"Name":"Data 2","Desc":"Second","Type":"date","$$hashKey":"uiGrid-0028"}, {"Name":"Data 3","Desc":"Third","Type":"date","$$hashKey":"uiGrid-002A"}, {"Name":"Term Date","Desc":"Termination","Type":"date","$$hashKey":"uiGrid-002C"}, {"Name":"2015.11","Desc":"11.1.2015","Type":"float","$$hashKey":"uiGrid-002E"}, {"Name":"2016.07","Desc":"7.1.2016","Type":"float","$$hashKey":"uiGrid-002G"}, {"Name":"Status","Desc":"Practice","Type":"string","OptionsCount":3,"$$hashKey":"uiGrid-002I"}, {"Name":"Phase","Desc":"","Type":"string","OptionsCount":5,"$$hashKey":"uiGrid-002K"}, {"Name":"EMFMT","Desc":"","Type":"string","OptionsCount":2,"$$hashKey":"uiGrid-002M"}, {"Name":"LAB Data","Desc":"","Type":"string","OptionsCount":2,"$$hashKey":"uiGrid-002O"}, {"Name":"Phase #","Desc":"Performance","Type":"integer","$$hashKey":"uiGrid-002Q"}, {"Name":"Letter 1","Desc":"Performance","Type":"date","$$hashKey":"uiGrid-002S"}, {"Name":"Letter 2","Desc":"Performance","Type":"date","$$hashKey":"uiGrid-002U"}, {"Name":"Letter 3","Desc":"Performance","Type":"date","$$hashKey":"uiGrid-002W"}, {"Name":"I Term","Desc":"","Type":"date","$$hashKey":"uiGrid-002Y"}, {"Name":"CO","Desc":"CO","Type":"bit","$$hashKey":"uiGrid-0030"}, {"Name":"Chart","Desc":"Chart","Type":"string","OptionsCount":3,"$$hashKey":"uiGrid-0032"}, {"Name":"Test money","Desc":"","Type":"money","$$hashKey":"uiGrid-0034"}, {"Name":"End-testing","Desc":"","Type":"money","$$hashKey":"uiGrid-0036"}, {"Name":"test1234","Desc":"","Type":"string","OptionsCount":5,"$$hashKey":"uiGrid-0022"}, {"Name":"testAbc","Desc":"","Type":"date","$$hashKey":"uiGrid-003A"}, {"Name":"test456","Desc":"","Type":"bit","$$hashKey":"uiGrid-003C"}, {"Name":"M","Desc":"Meaningful","Type":"string","OptionsCount":2,"$$hashKey":"uiGrid-003E"}, {"Name":"test date","Desc":"","Type":"date","$$hashKey":"uiGrid-003G"}, {"Name":"Service","Desc":"","Type":"string","$$hashKey":"uiGrid-003I"}, {"Name":"R Notes","Desc":"","Type":"string","OptionsCount":17,"$$hashKey":"uiGrid-003K"}, {"Name":"Appointment","Desc":"Appointment","Type":"string","OptionsCount":3,"$$hashKey":"uiGrid-003M"}, {"Name":"Connection","Desc":"Type of Connection","Type":"string","OptionsCount":6,"$$hashKey":"uiGrid-003O"}, {"Name":"A","Desc":"","Type":"string","OptionsCount":6,"$$hashKey":"uiGrid-003Q"}, {"Name":"Billing","Desc":"B","Type":"string","OptionsCount":6,"$$hashKey":"uiGrid-003S"}, {"Name":"E Connection","Desc":"","Type":"string","$$hashKey":"uiGrid-003U"}, {"Name":"Addend","Desc":"Data Addend","Type":"string","OptionsCount":2,"$$hashKey":"uiGrid-003W"}, {"Name":"IT","Desc":"","Type":"string","OptionsCount":4,"$$hashKey":"uiGrid-003Y"}, {"Name":"Portal","Desc":"","Type":"string","OptionsCount":5,"$$hashKey":"uiGrid-0040"}, {"Name":"Follow-up ","Desc":"","Type":"string","OptionsCount":3,"$$hashKey":"uiGrid-0042"}, {"Name":"Subspecial","Desc":"","Type":"string","OptionsCount":4,"$$hashKey":"uiGrid-0044"}, {"Name":"T","Desc":"Trainerh","Type":"string","$$hashKey":"uiGrid-0046"}, {"Name":"S","Desc":"","Type":"string","OptionsCount":3,"$$hashKey":"uiGrid-0048"}, {"Name":"A","Desc":"Date","Type":"string","$$hashKey":"uiGrid-004A"}, {"Name":"Dual","Desc":"Date joint","Type":"date","$$hashKey":"uiGrid-004C"}, {"Name":"Start D","Desc":"","Type":"date","$$hashKey":"uiGrid-004E"}, {"Name":"CO Addend","Desc":"Data COA","Type":"string","OptionsCount":1,"$$hashKey":"uiGrid-004G"}] Has anyone else experience this issue with ui-grid, and how did you resolve it? Or can anyone explain why it is creating these extra rows, and consistently only for these 2 rows?
Ok, so here's my answer. I apologize that this wasn't all in the original question, but there was too much code for it to be helpful. I'm writing an answer to be helpful for anyone else that runs into similar issues and gets stuck debugging (as I see that sharing as the purpose of SO). For background, a row is supposed to get selected during the page load process if the url has an Id for the row as a parameter. In the code the data is loaded into the grid.data. Then if the url has a parameter a loop executes on grid.data to find the matching row(s). If it is found, then it would call gridApi.grid.modifyRows(grid.data).then(action); where the action would be something like $timeout(function () { // Do this after the columns and rows processors have finished and it is all rendered. selectRows.forEach(function (row) { gridApi.selection.selectRow(row); }); gridApi.core.scrollTo(selectRows.pop(), grid.columnDefs[0]); }, 100); What is working for me now is to skip the "gridApi.grid.modifyRows" and just call the action. I think that code was in there earlier to update the grid if it had rendered before the data was retrieved and assigned to grid.data, but that is taken care of by waiting for onRegisterApi to fire, then assigning the grid.data.
Hide/Show all columns in kendo grid in one go
I have 120 columns in kendo grid, and have select all and deselect all functionality. If I go with for each loop it takes huge time to hide or show all column. Is there any way to hide/show all columns in one call. Just want to mention kendo showColumn/hideColumn is very slow. $(".some-class").each(function(){ var field1 = $(this).data("field"); input.find('label').addClass('enableCheck'); input.find('label').removeClass('disableCheck'); $("#grid-id").data("kendoGrid").showColumn(field1); }
Well I have created a demo of this kind of scenario for you: Show/Hide all columns This uses the inbuilt show/hide function for the grid and using a slightly larger grid than yours approx 130 columns on average it is completing the operation in sub 2 seconds. I have added a "timer" so you can see from the point it hits the looping of the columns to the end of the operation how long it takes. $("#clickme").on('click',function(){ var grid =$("#grid").data("kendoGrid"); var columns = grid.getOptions().columns; var start = new Date().getTime(); columns.forEach(function(me){ if(me.hidden !== undefined && me.hidden === true) { grid.showColumn(me.field); } else { grid.hideColumn(me.field); } //console.log(me); }); var end = new Date().getTime(); console.log(start,end, end-start); $("#timer").text((end-start)/1000 + ' Seconds to run' ); }); All this does is gets the columns within the grid and then checks to see if it is currently hidden (if it is then it will show it otherwise it will hide it) This is just bound to a simple button that you can click underneath the grid. For this type of operation I think sub 2 seconds is more than quick enough and "feels" about right for this number of columns as depending on how many rows you have on the current page it has to hide all those elements as well.
Hide table rows with expired content
Say I use a table to display scheduled content, and I want rows to disappear after their date has passed. Row 1 has Table title Row 2 has Date A Row 3 has Scheduled content A1 Row 4 has Scheduled content A2 Row 5 has Date B Row 6 has Scheduled content B1 Row 7 has Scheduled content B2 Row 5 has Date C Row 6 has Scheduled content C1 Row 7 has Scheduled content C2 etc. After Date A has passed, I want rows 2-4 to disappear/be hidden. I do this website on a volunteer basis, and there is nobody else available to help. I delete the expired rows on a daily basis, but I'm going on vacation and will be unplugged for two weeks. I don't have any example code, I'm a rookie. If you mean my html code, it's just a simple table. Sorry for not responding sooner, Jakub (https://stackoverflow.com/users/158014/jakub). Spent 12+ hours in hospital ER with my daughter right after my last edit yesterday. I will come back and fix the post to conform to Stackoverflow standards ASAP.
You can use jQuery library to hide certain parts of the website on certain dates. It should help on this case while you are off. First load jQuery, adding to the head section of your site: <script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script> Then your table in the body section: Then, near the end of the body tag, you create a rule for hiding content based on a date: <script type="text/javascript"> var now = new Date(); var futuretime1 = new Date("April 10, 2013"); if(now > futuretime1) { $("#div").hide(); } </script> This will hide #div when date passes "futuretime1". You can also use jQuery selectors for selecting the appropriate table row. Hope this helps.