Monday, October 03, 2005

IE assumes .CSV is HTML, Firefox and Opera get it right.

Sooo... I posted that .csv (comma-separated values) file containing some benchmarks as part of my previous post on the performance differences between browsers when populating multiple select boxes in 2 different ways. What I didn't notice until later, though, is that that file looks like crap if you click the link to it in Internet Explorer. IE seems to make an assumption like "Hmm, it doesn't have extension '.txt', so it must be HTML!" and it renders it as such. Of course, this .csv file doesn't contain any HTML tags, so it doesn't look pretty when IE makes that assumption:
MultiSelectPerformance.csv

For comparison, I made 2 copies of the CSV file:
MultiSelectPerformance.csv.txt
MultiSelectPerformance.csv.html

When I tried clicking the original .csv file link in Firefox and in Opera 8.5, they both behaved as I believe they should. They asked me if I wanted to open the .csv file with the application that is registered in Windows to handle files with that extension, Microsoft Excel, or if I wanted to save it to disk, or cancel.

Screenshots of those dialogs:

Firefox CSV file open dialogOpera CSV file open dialog


It strikes me as odd that IE, with its litigiously tight integration with Windows, didn't bother to check the Windows File Types list before jumping to the strange conclusion that .CSV is a typo for .HTML. It's possible that I could change my web server config files so it would send an appropriate 'Content-type:' header when .CSV files are served. But screw that, this is a stupid behavior in one browser, and I may want to serve a .CSV file on a web server someday where I can't touch the config files. I was determined to do something to handle it on the client side.

[to be continued...]

Thursday, September 29, 2005

Comparison of Multiple Select Box Population Performance

I was recently working on developing a web application for a team project at school, when I ran into a little problem. We had a list of 1881 items to put in a select box. That, in itself, was a no-brainer. The problem was, we wanted to have 10 select boxes on this page, each with all 1881 items in it.

So, since I was using JSP, I pulled the entire list of OPTION tags out and stuck it in a separate file, then used the include directive, like:

< %@ include file="optionList.jsp" % >

inside each of the 10 sets of SELECT tags, so the list was only stored in one place. However, this optionList.jsp file was 59KB, and this page needed to load reasonably fast, despite being served off my home server with a cable modem, and viewed at school with a flaky, unreliable wireless connection. Therefore, a page with over 590KB worth of text/html was just not going to work.

Well, I've dealt with manipulating select boxes using JavaScript before, so I decided to try putting all the options into an array of strings, and looping through each select box, and each element of the option array, to add all the options. Well, this worked fine in Firefox, but in IE, it took a ridiculous amount of time (roughly 2 minutes). With that kind of performance, we might as well just load the 590+ KB original page!

So, I did some research into javascript optimization, and explored the W3C DOM spec extensively. I created about 10 different methods of populating the select boxes, and ran each of them with timing code around them, in IE and Firefox. Eventually, I found a solution that performed reasonably well in IE and Firefox, and used it for the team project.

The key lines of code are:

var tmp = document.getElementById('selectBox_0').cloneNode(true);
// ...
var selectN = document.getElementById('selectBox_' + pickNum);
// ...
selectN.parentNode.replaceChild(tmp, selectN);

Basically, I created the first select box one option at a time, then cloned that select box object (with the 'true' parameter, to clone all child nodes as well) and replaced all the other select boxes with the clones. Then, I set some properties on the clones to make them unique (IDs, default blank options, etc). Dramatically faster than the other.

I've put together a benchmark page to test/demonstrate the original method of populating the select boxes (adding one option at a time, to one select box at a time), versus the method I found that worked so well. Then I ran the benchmark on several browsers, on several computers, and had some friends and co-workers try it, too. You can find the benchmark page here:

http://www.oatmealcookies.org/blogdl/
performance/MultiSelectPerformance.html


The benchmark results, as I've recorded them so far, can be found in a comma-delimited text file at:

http://www.oatmealcookies.org/blogdl/
performance/MultiSelectPerformance.csv


I recently found out that Opera 8.02 works about as fast as Firefox, even faster in some cases. I was impressed that the code that I'd tested thoroughly in IE and Firefox (but not Opera) actually RAN without errors, but the fact that it ran so fast was pretty cool.

Please feel free to run the benchmark and send me your results! The way that these measurements have been recorded is:

Click 'Run All'.. when tests are complete (ranges from 12 seconds to 5 minutes, depending on browser and platform), click 'Save Data', which populates a textarea at the bottom of the page, and selects it, so you can then copy it to your clipboard and post it in a comment on this blog entry. Please include all fields that are in that CSV file, including browser versions, OS, processor speed, etc.

Monday, August 08, 2005

Google search results that require subscriber-only login? Disable JavaScript!

Today I experienced something I've seen many times before, but it pissed me off enough to investigate this time. Many times, when I search for some info with google, some of the results that I click do not include the matched content, but instead take me to a login page, saying the content is restricted to subscribers only.

Today, the site was techtarget.com. I've found useful information on that site before, and it was the #3 result in my search (I searched for "tracking down wireless network interference"). Sometimes, it's possible to view these pages by viewing google's cached copy. This time, that didn't work either. Even the cached copy redirected me to a login page.

So, i tried looking at the http headers with LiveHttpHeaders extension in FireFox, and that's where I saw these URLs as the first two requests:

First, google's cache:
http://64.233.187.104/search?q=cache:JGSD_2iKWo0J:
searchmobilecomputing.techtarget.com/tip/1,289483,
sid40_gci1109438,00.html+tracking+down+wireless+
network+interference&hl=en&client=firefox-a


Second, a javascript page from techtarget:
http://searchmobilecomputing.techtarget.com/
pageScripts/0,294327,sid40,00.js


Everything after that was related to the techtarget login page.

So, the redirect is in the javascript, eh? So I used 'wget' to download the javascript file ("0,294327,sid40,00.js"), then opened it in my text editor ( TextPad), and searched for 'redirect'. I think the following is causing the redirect, although I haven't looked thoroughly through the whole script, because I didn't need to:


/*
Force login if content is members only.
Redirect to top in case document is loaded
in a frame or iframe.
*/
var forMembersOnly =
(typeof JSmembersOnly != "undefined" &&
JSmembersOnly == "on") ? true : false;
if (forMembersOnly && loggedIn != 1) {
var NextURL = window.top.location.href;
if (NextURL.indexOf(
"/ttCMAv2/Production_Center/" +
"Preview_Form_v2/1,2563,,00.html") == -1) {
var redirectURL;
if (typeof JSmembersLoginURL == "undefined" &&
JSmembersLoginURL == "") {
redirectURL =
(typeof JSlinkLogin != "undefined") ?
JSlinkLogin :
"http://searchMobileComputing.techtarget.com/" +
"loginMembersOnly/1,289498,sid40,00.html";
} else {
redirectURL =
((JSmembersLoginURL.indexOf(
"http://searchMobileComputing.techtarget.com") ==
0) ? "" :
"http://searchMobileComputing.techtarget.com") +
JSmembersLoginURL;
}
window.top.location.replace(redirectURL +
"?NextURL=" + escape(NextURL));
}
}


So, I just disabled javascript in my browser before clicking the link!
This is VERY EASY to do with FireFox and the
Web Developer Toolbar extension.

In my opinion, there's nothing wrong with doing this. They made the content available for google to index, but then deliberately prevented me from viewing it (bait and switch?). I just viewed it without javascript. It probably would have also worked to just use a text-only browser like links or lynx. This will probably not get around ALL cases of this annoying search result behavior, but it did help in this case.