1function fixTable(container) { 2 // Store references to table elements 3 var thead = container.querySelector('thead'); 4 var tbody = container.querySelector('tbody'); 5 6 // Style container 7 container.style.overflow = 'auto'; 8 container.style.position = 'relative'; 9 10 // Add inline styles to fix the header row and leftmost column 11 function relayout() { 12 var ths = [].slice.call(thead.querySelectorAll('th')); 13 var tbodyTrs = [].slice.call(tbody.querySelectorAll('tr')); 14 15 /** 16 * Remove inline styles so we resort to the default table layout algorithm 17 * For thead, th, and td elements, don't remove the 'transform' styles applied 18 * by the scroll event listener 19 */ 20 tbody.setAttribute('style', ''); 21 thead.style.width = ''; 22 thead.style.position = ''; 23 thead.style.top = ''; 24 thead.style.left = ''; 25 thead.style.zIndex = ''; 26 ths.forEach(function(th) { 27 th.style.display = ''; 28 th.style.width = ''; 29 th.style.position = ''; 30 th.style.top = ''; 31 th.style.left = ''; 32 }); 33 tbodyTrs.forEach(function(tr) { 34 tr.setAttribute('style', ''); 35 }); 36 [].slice.call(tbody.querySelectorAll('td')) 37 .forEach(function(td) { 38 td.style.width = ''; 39 td.style.position = ''; 40 td.style.left = ''; 41 }); 42 43 /** 44 * Store width and height of each th 45 * getBoundingClientRect()'s dimensions include paddings and borders 46 */ 47 var thStyles = ths.map(function(th) { 48 var rect = th.getBoundingClientRect(); 49 var style = document.defaultView.getComputedStyle(th, ''); 50 return { 51 boundingWidth: rect.width, 52 boundingHeight: rect.height, 53 width: parseInt(style.width, 10), 54 paddingLeft: parseInt(style.paddingLeft + 1, 10) 55 }; 56 }); 57 58 // Set widths of thead and tbody 59 var totalWidth = thStyles.reduce(function(sum, cur) { 60 return sum + cur.boundingWidth; 61 }, 0); 62 tbody.style.display = 'block'; 63 tbody.style.width = totalWidth + 'px'; 64 thead.style.width = totalWidth - thStyles[0].boundingWidth + 'px'; 65 66 // Position thead 67 thead.style.position = 'absolute'; 68 thead.style.top = '0'; 69 thead.style.left = thStyles[0].boundingWidth + 'px'; 70 thead.style.zIndex = 10; 71 72 // Set widths of the th elements in thead. For the fixed th, set its position 73 ths.forEach(function(th, i) { 74 th.style.width = thStyles[i].width + 'px'; 75 if (i === 0) { 76 th.style.position = 'absolute'; 77 th.style.top = '0'; 78 th.style.left = -thStyles[0].boundingWidth + 'px'; 79 } 80 }); 81 82 // Set margin-top for tbody - the fixed header is displayed in this margin 83 tbody.style.marginTop = thStyles[0].boundingHeight + 'px'; 84 85 // Set widths of the td elements in tbody. For the fixed td, set its position 86 tbodyTrs.forEach(function(tr, i) { 87 tr.style.display = 'block'; 88 tr.style.paddingLeft = thStyles[0].boundingWidth + 'px'; 89 [].slice.call(tr.querySelectorAll('td')) 90 .forEach(function(td, j) { 91 td.style.width = thStyles[j].width + 'px'; 92 if (j === 0) { 93 td.style.position = 'absolute'; 94 td.style.left = '0'; 95 } 96 }); 97 }); 98 } 99 100 // Initialize table styles 101 relayout(); 102 103 // Update table cell dimensions on resize 104 window.addEventListener('resize', resizeThrottler, false); 105 var resizeTimeout; 106 107 function resizeThrottler() { 108 if (!resizeTimeout) { 109 resizeTimeout = setTimeout(function() { 110 resizeTimeout = null; 111 relayout(); 112 }, 500); 113 } 114 } 115 116 // Fix thead and first column on scroll 117 container.addEventListener('scroll', function() { 118 thead.style.transform = 'translate3d(0,' + this.scrollTop + 'px,0)'; 119 var hTransform = 'translate3d(' + this.scrollLeft + 'px,0,0)'; 120 thead.querySelector('th').style.transform = hTransform; 121 thead.querySelector('th:nth-child(2)').style.transform = hTransform; 122 [].slice.call(tbody.querySelectorAll('tr > td:first-child,tr > td:nth-child(2)')) 123 .forEach(function(td, i) { 124 td.style.transform = hTransform; 125 }); 126 }); 127 128 /** 129 * Return an object that exposes the relayout function so that we can 130 * update the table when the number of columns or the content inside columns changes 131 */ 132 return { 133 relayout: relayout 134 }; 135}
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.