After working on overlay a bit, I noticed some things in tableheader.js which I thought could be improved.
Minor changes:
- removed the User Agent testing for anything less than IE7, and replaced it with feature detection.
- introduced some caching variables. Shouldn't give a dramatic speed increase, but since tracker() is called on every scroll, every micro optimization counts.
- Replaced 2 scroll bounded to 2 different elements with 1 scroll bound to an array of 2 different elements.
- Namespaced scroll() and resize() events.
- removed extra space in a comment.
- added context in 2 jquery objects.
Major change:
- Took out the eval(). My first thought when seeing the eval() would be that it would be a major speed hog. However, the eval() was probably only there because they wanted to parse the function only there. Since there is no real alternative for eval() to my knowledge, I changed the way it worked.
(By the way, this implementation feels broken, since it only allows 1 function to be passed to tableheader.js. I didn't try fixing this, because I didn't know whether it was by design or not.)
Instead of a function, I'm passing a selector, and duplicated it in tableheader js, where the function takes the selector as an argument. This is justified IMHO, because the function is generic enough to be used in tableheader.js.
I also modified the function with a second if condition for all non IE browsers (if they don't have a css filter property, they don't need to be tested for a specific filter property).
Done some benchmarking to prove my point.
var start = new Date().getTime();
var i = 1000;
while (i--) {
var topOffset = eval(Drupal.settings.tableHeaderOffset + '()');
}
var end = new Date().getTime();
var time = end - start;
var start2 = new Date().getTime();
var i2 = 1000;
while (i2--) {
var topOffset = offsetHeight('#toolbar');
}
var end2 = new Date().getTime();
var time2 = end2 - start2;
alert('Eval: ' + time + ', function: ' + time2);
- Windows 7, Firefox 3.6.3: Eval: 83, function: 65
- Windows 7, Opera 10.53: Eval: 58, function: 38
- Windows 7, Safari 4: Eval: 32, function: 20
- Windows 7, IE8: Eval: 202, function: 125
Comment | File | Size | Author |
---|---|---|---|
#27 | tableheader-cleanup7b.patch | 3.73 KB | casey |
#22 | tableheader-cleanup7.patch | 9.82 KB | casey |
#20 | tableheader6.patch | 8.85 KB | casey |
#18 | tableheader5+anchor.patch | 10.34 KB | casey |
#17 | tableheader4+anchor.patch | 10.37 KB | casey |
Comments
Comment #1
Kiphaas7 CreditAttribution: Kiphaas7 commentedForgot the patch...
Comment #2
Kiphaas7 CreditAttribution: Kiphaas7 commentedCleaned up the previous patch, and moved the function for calculating the offset into a drupal namespaced function. That way it can also be used outside tableheader.js wihout having to duplicate the code (for example in overlay).
Comment #3
Kiphaas7 CreditAttribution: Kiphaas7 commentedSetting back to needs work, still some stuff to do...
Comment #4
casey CreditAttribution: casey commented@Kiphaas7, I talked to you about a more generic approach for displaced elements. Please have a look at #787940: Generic approach for position:fixed elements like Toolbar, tableHeader first.
Comment #5
Kiphaas7 CreditAttribution: Kiphaas7 commentedawesome, postponing this issue untill that one lands. No sense doing double work.
Comment #6
casey CreditAttribution: casey commentedI also have another idea on how to improve/speedup tableheader.js
1. add a div right before the table with position:absolute, overflow:hidden and exactly match table position/size (only recalculate on window.resize)
2. copy tableheader into that div with position:fixed and top:Drupal.displace.getDisplacement("top") (#787940: Generic approach for position:fixed elements like Toolbar, tableHeader)
I think the stickytable header will then only be visible while the table is in your viewport. Advantage is that you don't need to track window.onscroll.
Edit: this idea is not going to work as overflow:hidden doesn't affect children with position:fixed
Comment #7
casey CreditAttribution: casey commentedWe can already cleanup tableheader.js. If #787940: Generic approach for position:fixed elements like Toolbar, tableHeader would get committed we only have to change one line.
Patch introduces a Drupal.tableHeader object that can be reused. jQuery selectors are cached and cell width calculation is only performed when the sticky header is actually visible.
Comment #8
casey CreditAttribution: casey commentedI uploaded a wrong patch.
Comment #9
casey CreditAttribution: casey commentedWith position:fixed test like in KipHaas7' patch.
Comment #10
jbrown CreditAttribution: jbrown commentedeval() really shouldn't be in core: http://drupal.org/node/172169
See also #743338: Position of sticky table headers is not updated when shortcut bar is toggled
Comment #11
casey CreditAttribution: casey commentedPlease read #7 and #787940: Generic approach for position:fixed elements like Toolbar, tableHeader.
The one line that then will be changed is the one using eval();
Comment #12
casey CreditAttribution: casey commentedMinor improvements.
Comment #13
Kiphaas7 CreditAttribution: Kiphaas7 commentedpatch does not apply anymore since #787940: Generic approach for position:fixed elements like Toolbar, tableHeader landed.
Straight re-roll of #12.
Comment #14
casey CreditAttribution: casey commentedReroll as #787940: Generic approach for position:fixed elements like Toolbar, tableHeader landed
Comment #15
Kiphaas7 CreditAttribution: Kiphaas7 commentedLol @ 2 identical rerolls within 1 minute :D.
Please see my followup patch in #787940: Generic approach for position:fixed elements like Toolbar, tableHeader. It moves the test for position:fixed to drupal.js, which should increase performance a bit (1 dom operation instead of 2, seperately done by tableheader.js and displace.js).
Comment #16
Kiphaas7 CreditAttribution: Kiphaas7 commentedfollowup for #787940: Generic approach for position:fixed elements like Toolbar, tableHeader has landed, so here's a reroll with the changed position:fixed test.
Comment #17
casey CreditAttribution: casey commentedI found some issues on anchors being invisible due to tableheader (and displaced elements): #546126: Toolbar interferes with anchor links and #567754: Wrong anchor adjustment in tableheader.js.
In the first we discussed using the hashchange event. This is however not sufficient; to reproduce:
- go to admin/people/permissions#module-filter
- scroll away from the anchor
- press ENTER on the addressbar of your browser; window scrolls to the anchor, the hashchange event however isn't fired.
Therefor I tried it to recognize scroll events triggerd to scroll to the anchor. And with success.
Next issue is that there might be several scripts that want to adjust the scrollTop to get the anchor visible (currently tableheader.js and displace.js). Therefor I introduced a new event "drupalScrollToAnchor". I added the trigger to drupal.js because its just a small piece of code.
(Note that this isn't working with overlay yet. For #668640: Overlay shouldn't be based on jQuery UI Dialog it just takes 3 lines).
Comment #18
casey CreditAttribution: casey commentedRemoved an obsolete line of code.
Comment #19
Kiphaas7 CreditAttribution: Kiphaas7 commentedlooks good, tried it in a few browsers and worked. Obviously overlay needs some love, but without overlay, fine.
Overlay issues shouldn't be fixed in this issue though.
Comment #20
casey CreditAttribution: casey commentedI also found out that tableheader was hiding the focused element when using TAB-navigation. Therefor I opened a seperate issue: #800270: Anchor/focus hidden beneath toolbar/tableheader (CKEditor full screen menu).
I wasn't really happy to add code to drupal.js and moved it into displace.js; that's what the code is about anyway. Only downside is that tableheader is dependent upon displace.js (but that shouldn't be a problem).
(So to test this patch you also have to apply #800270: Anchor/focus hidden beneath toolbar/tableheader (CKEditor full screen menu))
Comment #21
Kiphaas7 CreditAttribution: Kiphaas7 commentedSoooo, this is a bug report now? :)
Comment #22
casey CreditAttribution: casey commentedRemoved dependencies on other patches. Lets get this in first.
Comment #23
casey CreditAttribution: casey commentedAnyone?
Comment #24
casey CreditAttribution: casey commentedThere is also a bug in the current tableheader.js in certain cases triggering the following error:
To reproduce that error open a page with a table and add anon-existing anchor to the URL, e.g.: /admin/people/permissions#nonexistent-anchor
This patch fixes that bug too (maybe this will get some attention).
But tableheader.js really is a mess.
Comment #25
james.elliott CreditAttribution: james.elliott commentedThe patch looks good and works well.
Comment #26
Dries CreditAttribution: Dries commentedI've tested this patch and I've found it to work.
I've also looked at the code and couldn't find anything wrong with it -- it is slightly easier to read.
Hence, I've decided to commit it to CVS HEAD.
Comment #27
casey CreditAttribution: casey commentedIE is still having trouble with complex tables (like on the modules page).
Also removed some code that only is supposed there if and only if #787940: Generic approach for position:fixed elements like Toolbar, tableHeader lands.
Comment #28
casey CreditAttribution: casey commented#27: tableheader-cleanup7b.patch queued for re-testing.
Comment #29
droplet CreditAttribution: droplet commentedComment #30
nod_Forgot this one…
The main issue was with
eval()
, I made a patch taking it out a different way over there : #1417378: Remove eval() from tableHeader JavaScript if someone has some time to review that'd be nice.I'm not sure about the rest of the changes didn't look too closely.
Comment #31
nod_closing this for #1574738: Rewrite tableheader.js, there is a working patch over there.