Skip to content

Looks like IE8 doesn't like parsers set as class names? #74

Closed
camartinez1229 opened this Issue May 19, 2012 · 13 comments

2 participants

@camartinez1229

Hello again, Mottie! I'm back with a new issue, haha. I've currently upgraded to Tablesorter 2.3.2, while still keeping the pager plugin from 2/16/12, because newer versions slow down IE, as I mentioned previously. I realized my custom parser wasn't sorting correctly under 2.0.31 in IE8, but testing in the latest, it sorts properly. However, I've also tried to migrate my parser settings to class names on my headers instead of using the headers option in the initialization script, because I'm wanting to use the sorter on two tables with different columns. Well, most browsers play nicely with the class names, even the previously dreaded IE9. But of course, there always has to be one spoiled brat in the bunch, haha, and this time it's IE8.

I did some troubleshooting with console logging, and figured out that the getData function does recognize the class names, but the values don't get passed to the getParserById function, for some reason. name...is nameless in IE8 (haha). And so, without those names being passed, the script just detects parsers on its own, ignoring my custom parser in the process.

Interestingly, IE8 does pick up data-sorter="foo" correctly. So, for a workaround for now, I'm setting both class names and data-sorter names. Data-sorter is not available in 2.0.31, which I'm currently sticking Opera with via htaccess, because Opera has unusually slow initial cache build times with 2.3.2, ~6000ms. That's a marked deterioration from the already slightly slow ~1000ms seen in 2.0.31.

I'm not highly concerned about either the issue with IE8 or Opera's sluggishness, because I have workarounds in place. But, I thought I'd bring them up, in case you want to address them.

Correction: IE8 doesn't appear to support data-sorter="foo". I just discovered that in my testing, I had re-defined my custom parser as a header option at some point, and had forgotten to remove it, till I saw that it causes the other table I want to be sortable, to sort incorrectly. Well, this messes things up for me. Hopefully not too bad, though...I can still attach different initialization scripts to my tables, which should work. Or, I still haven't tried setting inline metadata yet--that should also work.

@Mottie
Owner
Mottie commented May 19, 2012

Hmmm, ok I'll have to look at this again. In a previous version the getData wasn't correctly handling false settings as instead of getting a string from jQuery data, it was getting a boolean (data-sorter="false") and thinking the data wasn't there ....

I know the slow down in 2.3.2 is because of the natural sorting algorithm. It does more chunking of data, whereas the previous alphanumeric sort only "chunked" the first set.

@Mottie
Owner
Mottie commented May 19, 2012

Well when IE9 runs in IE8 compatibility mode, it seems to work fine. But when I try it in IE Tester (the only thing I have available to me), none of the document pages are working... o.O

I think I found the problem though... the getData function will look at the class name tablesorter-header, assigned by the cssHeader option, and it will try to set the sorter to header. I'll have it fixed in the next version.

@camartinez1229

Oh, I hated using IETester. It would always be buggy for me, and often crash. I only ever used it for testing IE6 under Windows Vista/7, back when I was supporting IE6 on a previous site. I got so fed up with IETester that I just migrated my IE6 testing to an XP virtual machine, (now XP Mode under Windows 7), where I had a native IE6 install. But now, I don't worry about that, because I support neither IE6 nor IE7 anymore. I still use IE9's compatibility view settings to test my site as IE8, and occasionally as IE7, just so I could laugh at the broken layout that I could sink time into trying to fix, but most likely won't, haha.

Anyway, I've come up with a workaround for IE8. Since it currently seems to only respect parser settings declared as header options in the initialization script, I added classes to my tables, and then made a switcher based on those classes, modeled after the following example:

if ($('table').hasClass('foo')) {var options = {headers:{0:{sorter:false},1:{sorter:'text'},4:{sorter:'mycustom'}}};}
else {var options = {headers:{0:{sorter:false},1:{sorter:'text'},5:{sorter:'mycustom'}}};}

$('.pager').show();
$('table').tablesorter(options)
.bind("sortEnd",function(){blah})
.tablesorterPager({container: $(".pager")})

Seems to be working for me so far. Glad to finally have IE8 bowing to my will, haha.

I've also fixed Opera's sluggishness! Believe it or not, it wasn't the natural sort that slowed it down...I saw no difference in speed/times by using the older text sorting method. Instead, it was having debugging enabled that slowed it down! On a hunch, I decided to measure times (using a stopwatch), with debugging disabled. Knowing that Firefox 3.5/3.6 would sometimes hang depending on where I was console logging some variables, I wondered if Opera could be affected similarly.

Here are some example times I got (with resetting my cache after each run). Remember, this is 11 columns and 700+ rows I'm dealing with in my main table:

TS 2.3.2, debug:true: ~14 seconds
TS 2.0.31, debug:true: ~11 seconds
TS 2.0.31, debug:false: ~5.5 seconds
TS 2.3.2, debug:false: ~6 seconds

Of course, it's tough to get exact timings with a stopwatch, but there's no denying that things are much faster without debugging enabled, haha. I do wonder why Opera is the only modern browser to slow down with it on, though. Ah well, it doesn't matter too much. At least I've nearly closed the performance gap between Opera and the rest. Others tend to be 1-3 seconds faster, but you would hardly notice unless you're using a stopwatch :P

@Mottie
Owner
Mottie commented May 19, 2012

Haha nice work!

I'm about to push another version with the fixes to the getData() function.... I've also added an "Overall initialization time" debug message which reports the time from the plugin being called to after the widgets have completely applied.

Oh and I've modified the zebra and columns widgets to use document fragments to speed up application as well.

@Mottie
Owner
Mottie commented May 19, 2012

Alrighty, try version 2.3.3 and see if fixes the problems with IE8 since apparently I can't test it =/

@camartinez1229

Testing IE8 with 2.3.3, I still see the same problem with it not using defined class names or jQuery data. Here is some sample debug output from IE8 and IE9, if it helps:

IE8 w/ Firebug Lite, Debug Output (Classes and jQuery data set)

Built headers (12ms) 
[th.sorter-false, __th.sorter-text__, th.sorter-text, th.sorter-digit, __th.sorter-peak__, th.sorter-shortdate, th.sorter-digit, th.sorter-digit, th.sorter-digit, th.sorter-digit, th.sorter-shortdate]

Checking if value was empty on row 0, column:0: 1
Checking if value was empty on row 0, column:1: (There’s Got To Be) More To LifeHall Of Fame Entry #12, 03/19/05
Checking if value was empty on row 0, column:2: Stacie Orrico
Checking if value was empty on row 0, column:3: 70
Checking if value was empty on row 0, column:4: 2-2
Checking if value was empty on row 0, column:5: 12/27/03
Checking if value was empty on row 0, column:6: 29
Checking if value was empty on row 0, column:7: 57
Checking if value was empty on row 0, column:8: 33
Checking if value was empty on row 0, column:9: 18
Checking if value was empty on row 0, column:10: 04/23/05

column:0; parser:digit; string:max; empty: bottom
column:1; parser:__shortDate__; string:max; empty: bottom
column:2; parser:text; string:max; empty: bottom
column:3; parser:digit; string:max; empty: bottom
column:4; parser:__text__; string:max; empty: bottom
column:5; parser:shortDate; string:max; empty: bottom
column:6; parser:digit; string:max; empty: bottom
column:7; parser:digit; string:max; empty: bottom
column:8; parser:digit; string:max; empty: bottom
column:9; parser:digit; string:max; empty: bottom
column:10; parser:shortDate; string:max; empty: bottom

Building cache for 736 rows (1029ms)
Overall initialization time (1151ms)
Rebuilt table (154ms)

IE9 w/ Firebug Lite, Debug Output (Classes and jQuery data set)

Built headers (13ms)
[th.sorter-false, th.sorter-text, th.sorter-text, th.sorter-digit, th.sorter-peak, th.sorter-shortdate, th.sorter-digit, th.sorter-digit, th.sorter-digit, th.sorter-digit, th.sorter-shortdate]

Checking if value was empty on row 0, column:0: 1

column:0; parser:digit; string:max; empty: bottom
column:1; parser:text; string:max; empty: bottom
column:2; parser:text; string:max; empty: bottom
column:3; parser:digit; string:max; empty: bottom
column:4; parser:peak; string:max; empty: bottom
column:5; parser:shortDate; string:max; empty: bottom
column:6; parser:digit; string:max; empty: bottom
column:7; parser:digit; string:max; empty: bottom
column:8; parser:digit; string:max; empty: bottom
column:9; parser:digit; string:max; empty: bottom
column:10; parser:shortDate; string:max; empty: bottom

Building cache for 736 rows (130ms)
Overall initialization time (230ms)
Rebuilt table (357ms)

IE8 w/ Firebug Lite, Debug Output (Only jQuery data set)

Built headers (12ms) 
[th, th.he, th.he, th.he, th.he, th.he, th.he, th.he, th.he, th.he, th.he]
Checking if value was empty on row 0, column:0: 1
Checking if value was empty on row 0, column:1: (There’s Got To Be) More To LifeHall Of Fame Entry #12, 03/19/05
Checking if value was empty on row 0, column:2: Stacie Orrico
Checking if value was empty on row 0, column:3: 70
Checking if value was empty on row 0, column:4: 2-2
Checking if value was empty on row 0, column:5: 12/27/03
Checking if value was empty on row 0, column:6: 29
Checking if value was empty on row 0, column:7: 57
Checking if value was empty on row 0, column:8: 33
Checking if value was empty on row 0, column:9: 18
Checking if value was empty on row 0, column:10: 04/23/05

column:0; parser:digit; string:max; empty: bottom
column:1; parser:__shortDate__; string:max; empty: bottom
column:2; parser:text; string:max; empty: bottom
column:3; parser:digit; string:max; empty: bottom
column:4; parser:__text__; string:max; empty: bottom
column:5; parser:shortDate; string:max; empty: bottom
column:6; parser:digit; string:max; empty: bottom
column:7; parser:digit; string:max; empty: bottom
column:8; parser:digit; string:max; empty: bottom
column:9; parser:digit; string:max; empty: bottom
column:10; parser:shortDate; string:max; empty: bottom

Building cache for 736 rows (724ms)
Overall initialization time (837ms)
Rebuilt table (975ms)

IE9 w/ Firebug Lite, Debug Output (Only jQuery data set)

Built headers (15ms)
[th, th.he, th.he, th.he, th.he, th.he, th.he, th.he, th.he, th.he, th.he]

Checking if value was empty on row 0, column:0: 1

column:0; parser:digit; string:max; empty: bottom
column:1; parser:text; string:max; empty: bottom
column:2; parser:text; string:max; empty: bottom
column:3; parser:digit; string:max; empty: bottom
column:4; parser:peak; string:max; empty: bottom
column:5; parser:shortDate; string:max; empty: bottom
column:6; parser:digit; string:max; empty: bottom
column:7; parser:digit; string:max; empty: bottom
column:8; parser:digit; string:max; empty: bottom
column:9; parser:digit; string:max; empty: bottom
column:10; parser:shortDate; string:max; empty: bottom

Building cache for 736 rows (119ms)
Overall initialization time (222ms)
Rebuilt table (367ms)

I guess you can't bold text in formatted code, huh? Any attempted emphasis above is mine (tried to highlight the columns IE8 gets wrong). Using IE's built-in console, I would only see the useless "[Object object]" right after the line about building headers. Firebug exposes such objects, however. So, I totally expected IE8 to be returning some useless or empty object, but actually, it's a log of my th's, and it's the same data as IE9...weird. But, IE8 obviously does something different with the data, because the script then checks the data in each of the headers and detects parsers on its own, whereas IE9 doesn't appear to check them. Hmmm... I wouldn't be surprised if it's IE8 failing on some string or regex function that matches the class names or jQuery data to the available parsers. I know IE <9 can be problematic with those. Then again, it could be something different... I guess you just never know, when you're dealing with IE :\ Haha.

@camartinez1229

I got IE8 working correctly!!! After much experimenting with the script debugger in the IE Developer Tools, I traced the issue to the CSS selector for the headers filter: $headers.filter(':not([colspan])[data-column="'+i+'"]:last');. IE8 has a CSS bug, where it thinks all table cells have a colspan. See http://css-tricks.com/ie8-colspan/ for details. As is, I guess the selector excludes all headers in IE8, prompting the script to then detect column parsers on its own based on the first td row's data. I merely removed :not([colspan]), and that got things working correctly for me. None of my cells have a colspan greater than one. However, I imagine things could get messed up, if there are cells spanning more than one column. So...what to do about that? That, I'm not sure... At least I've isolated the problem area, though! (As far as I know, anyway.)

@camartinez1229

Just came up with a quick and dirty fix for preserving any colspan greater than one! Since only IE8 assumes a default colspan of 1 on every table cell, according to the article I linked above, you can work around that:

Add this:

var ie8sucks = $.browser.msie&&parseInt($.browser.version)==8 ? '[colspan="1"]' : ':not([colspan])';

Then modify this:

$headers.filter(ie8sucks+'[data-column="'+i+'"]:last');

Of course, feel free to change the variable name, haha. And, there may be a more elegant solution than this, but hey, it works for me :)

@Mottie
Owner
Mottie commented May 20, 2012

Wow thanks for all of the work and research you put into this! I really appreciate it!

I'll try to figure out a good method without using $.browser.msie since I think it's going away.

@camartinez1229

You could try looping through the table headers with an each function, and getting the value of attr('colspan'). As far as I understand, without looping, you can only check the attr of one matched element. Anyway, IE8 will return a colspan of 1 by default, while every other browser should return undefined. Then, you can modify the headers selector based on the returned value... While this ought to work, and without using $browser, I can't help but think there could be a better way...

A few moments later...

Aha! There is a simpler way...why not just double the header selector? I modified it to (':not([colspan])[data-column="'+i+'"]:last,[colspan="1"][data-column="'+i+'"]:last'), which should take care of all browsers, no browser sniffing or attr looping required. With it, IE8 still recognizes my parser classes correctly, as do modern browsers. I think this way is a winner! What do you think?

@Mottie
Owner
Mottie commented May 20, 2012

That looks like a winner! Thanks again for all of your hard work and input! I'll have this included in the next update, say... in the next 5 minutes or so ;)

@camartinez1229

2.3.4 is working perfectly! Thanks :)

@Mottie
Owner
Mottie commented May 20, 2012

happy dance

@Mottie Mottie closed this May 20, 2012
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.