I have a table with resizing functionality. Actually, it is not a <table>
element. I use the cluster of <div>
elements.
Briefly, my resizing function is a nested 'for' loops. It is something like this:
function resizeTable (putedCellWidth) {
for (var r = 0; r < rows.length; r++) {
for (var c = 0; c < rows[r].cells.length; c++) {
rows[r].cells[c].domNode.style.width = putedCellWidth + 'px';
}
}
}
As I understand, each rows[r].cells[c].domNode.style.width = putedCellWidth + 'px';
causes the full document redraw. So, if a table is large enough, then table resizing extremely slows down the browser.
I tried to use throttling (100 ms) to reduce the amount of resize events, but if a table is large enough, then even a single resizing takes too much time.
Can I assign all width
properties first, and only after that launch the single redraw?
I have a table with resizing functionality. Actually, it is not a <table>
element. I use the cluster of <div>
elements.
Briefly, my resizing function is a nested 'for' loops. It is something like this:
function resizeTable (putedCellWidth) {
for (var r = 0; r < rows.length; r++) {
for (var c = 0; c < rows[r].cells.length; c++) {
rows[r].cells[c].domNode.style.width = putedCellWidth + 'px';
}
}
}
As I understand, each rows[r].cells[c].domNode.style.width = putedCellWidth + 'px';
causes the full document redraw. So, if a table is large enough, then table resizing extremely slows down the browser.
I tried to use throttling (100 ms) to reduce the amount of resize events, but if a table is large enough, then even a single resizing takes too much time.
Can I assign all width
properties first, and only after that launch the single redraw?
-
4
Set the table to
display:none
before you resize and then back toinline
orblock
afterwards (whichever is relevant). – Reinstate Monica Cellio Commented Sep 23, 2015 at 10:10 - @Archer, nice sugestion, but hide the table waiting the end of the process will do the table disappear and appear, no? – Lucas Konrath Commented Sep 25, 2015 at 15:35
- 1 Are you showing tabular data (i.e. spreadsheet)? If so, have you tried with an actual <table> tag? It is perfectly fine to use "real" tables for this case. Since table cells width are all the same for a given column (colspan not withstanding), I would suppose that a browser only has to get and then pute the width of the first cell for every column and then only apply this value to all the other cell of the same column. Thus reducing the amount of calculation and DOM read access (per opposition where the browser has to get ALL divs' values, pute for ALL and then apply values). – redrum Commented Sep 25, 2015 at 17:45
- @Archer, thank you! That boosted my tables, but only for a while. For huge amount of data it still works slowly. But this amount is greatly bigger now, than before. – splash27 Commented Sep 26, 2015 at 17:43
-
@redrum,
<table>
is not suitable for me. My table uses colspans and separate column resizing, which work incorrect in<table>
. That's why I decided to use the cluster of<div>
. – splash27 Commented Sep 26, 2015 at 17:46
5 Answers
Reset to default 1Give width in percent despite pixels in order to achieve responsive layouts. If percent can't be used for any reason then DocumentFragment is the best bet in this case. It is intended for the temporary storage of the DOM structures. It won't calls the rendering engine of the browser until the modified fragment is inserted back to the document.
This is how a portion of the document would be fragmented.
var elem = document.getElementById("resizableTable");//assumes resizableTable is the id of the element has to modify
var frag = document.createDocumentFragment(); //method creates an imaginary node object with all properties.
frag.appendChild(elem);
Now iterate through the fragment to make the changes and then insert back the frag. This won't redraw the doc each time when you change something in the fragment.
PS: I know, I am late. But, thought this could help someone who need to do the same.
After taking another look at my answer, I don't think it'll be much better for performance. I found a function on another answer that could solve the performance problem by replacing the class rules.
- add a
<style>
tag in the<head>
section of the html document with one class:.dynamic-width {width: /*initial width here*/}
and add this class to all your "table cells"; Create the function below (from @Oriol's answer):
function setStyle(cssText) { var sheet = document.createElement('style'); sheet.type = 'text/css'; /* Optional */ window.customSheet = sheet; (document.head || document.getElementsByTagName('head')[0]).appendChild(sheet); return (setStyle = function(cssText, node) { if(!node || node.parentNode !== sheet) return sheet.appendChild(document.createTextNode(cssText)); node.nodeValue = cssText; return node; })(cssText); };
Then call it in your resize event handler like this:
function resizeTable(putedCellWidth){
setStyle('.dynamic-width{ width: '+ putedCellWidth+'px; }');
}
This is expected to be faster because changing the class rules makes one write to the DOM O(1) as opposed to changing the rule on each cell O(n). This is true if the speed of visually applying the css rule is negligible.
There's a couple ways you might go about it. One have an event that gets fired when the user has stopped resizing their page for longer than say 150ms. That way it only fires once at the end.
Transform animations such as scale don't cause a redraw and if you're ok with the text getting smaller that would be less expensive. You can scale the whole table.
I don't know what your requirements are but a better approach is to let css naturally handle resizing since it's faster at it. You would have to set your columns with percentages beforehand.
I believe you can use requestAnimationFrame
to batch DOM updates and prevent layout thrashing. I heard about this idea from various virtual DOM implementations.
eg. in your case something like this might work.
function resizeTableCell (domNode, putedCellWidth) {
requestAnimationFrame(function() {
domNode.style.height = putedCellWidth + 'px';
});
}
It is written up here.
From the code snippet you have shared, I suspect you are avoiding the use of jquery... but fortunately, this is the kind of thing jquery shines at; DOM manipulation.
I don't know how the resize event of your "table" is triggered... (mouse drag? window resize? container change?);
If I were you, this is how I would handle this.
- Tag the "table" (outermost div) with a class-name e.g.
.draggable-table
. Also tag the "rows" as.row
or.tr
and the cells as.cell
or.td
; Write the below event handler:
function resizeTable(putedCellWidth){ $('.draggable-table .td').css('width', putedCellWidth+'px'); }
I've not looked at the internals of how jquery implements it, but I'm sure it's in an efficient manner that will be much faster than your nested loop.
If you don't use jquery at all, you really should, if you deal with the DOM a lot. If you are worried about the size it adds to your project, use a cdn and you benefit from the fact that it may already be cached in your users' browsers right from the first time they are visiting your site.
发布者:admin,转转请注明出处:http://www.yc00.com/questions/1744618731a4584211.html
评论列表(0条)