Category Archives: Programming

Slashdot CSS Makeover

Slashdot, one of the most widely known technology sites around the world has finally had a CSS makeover. The idea of retooling Slashdot was bantered around back in 2003, however the likelihood of anything happening seemed slim. At the time, there didn’t seem to be any serious enthusiasm to rebuild the backend, slashcode – with the general sentiment being “if you feel like hacking up slashcode, then we’d consider using it”. Slashdot has been running on a similar HTML 3.2 base for some eight years, simply because “it worked” and that was really good enough at the time.

It wasn’t long after the idea was mentioned before someone took it upon themselves to start the ball rolling. One of the first largely publicised steps was done by Daniel M. Frommelt, whose two articles published on A List Apart, Retooling Slashdot with Web Standards and Retooling Slashdot with Web Standards Part II garnered a lot of support. These two articles demonstrated how a huge site like Slashdot can be broken down and reworked into valid, semantic HTML.

The end product for Slashdot is a mostly validate HTML 4.01 document – which is a huge step forward. It would have been awesome if the xHTML utopia was realistic, however as with many sites, the advertisements and user contributed content prohibit it. The single largest point of interest about the retooling is the paradigm shift in authoring the HTML. The existing site was built using tables for structure and inline font tags for styling. This has now been replaced with divs for layout/structure, semantic markup and CSS for the presentation.

Since there has now been serious work done on Slashcode, we might see more frequent updates and features added to it.

JavaScript ParseInt Cast Error

It would appear there is some sort of an auto-casting problem in JavaScript. I have an external JavaScript file included into a page which defines a set of arrays, a line from the file looks like this:

  1. var resortPAArray = new Array('("1 Bed","1 Bedroom","2","3")','("2 Bed","2 Bedroom","3","5")','("Penthouse","Penthouse","4","10")');

The two numbers in each inner array represent the minimum and maximum people allowed to stay in that room type, for instance a 2 Bed bedroom can sleep a minimum of three and a maximum of five. There is a line in the JavaScript file for each building and they are used to auto-populate a booking form (to save posting back to the server on every change). The scripts were executing without error, until we added a room type which allowed ten (10) or more people in it.

When you select the building, it uses the inner arrays to populate a dropdown box with the room types (1 Bedroom, 2 Bedroom, ..). Once you select the room type, it then populates the next dropdown with the corresponding min/max people for that room type. Out of interest, the min/max values are assigned as follows where tmpArray represents an inner array:

  1. minpax=tmpArray[2];
  2. maxpax=tmpArray[3];

From here, those values are used in a for loop as follows:

  1. for (var i=minpax; i<=maxpax; i++) {
  2. // code here
  3. }

Remember, at this point the script is executing without any problems. When the values are assigned to the minpax and maxpax variables, they are technically strings – since they are defined in the inner arrays with quotes around them. Conveniently, JavaScript auto-casts values for you – as such the strings are cast to a numeric internally and the mathematic comparison is done.

Unfortunately, when a string value of 10 was assigned to maxpax, the for loop never executed and the as such, you couldn’t select how many people you wanted in that room. Initially, it made no sense at all. The JavaScript file for this building was structurally sound, no missing quotes, brackets or commas. All the values were in place, no strange characters at all – it was, for all intensive purposes, just like all the others.

The solution was quite simple, explicitly cast the values for minpax/maxpax when they are initially assigned or during the for loop.

  1. for (var i=parseInt(minpax); i<=parseInt(maxpax); i++) {
  2. // code here
  3. }

ADO RecordSet GetRows

ActiveX Data Objects (ADO) enable you to access and manipulate data from a variety of different sources. Through ADO, you can connect to various databases such as Access, mySQL, PostgreSQL, MSSQL, Oracle and more. Once connected you can execute SQL against the database, as per normal.

ADO provides a series of objects, methods and properties to make your life as a developer easier. One such object is the RecordSet, which provides a GetRows method. GetRows purpose is to copy a series of records from a populated RecordSet object and place them into an array. You can specify the number of rows to copy, where to start copying from and what fields in the RecordSet you’d like copied. The general format is as follows:

myArray = myRecordSet.GetRows(<number of rows>, <starting position>, <fields>)

After consulting the documentation for the method on MSDN, it appears that calling the GetRows method actually advances the current cursor position in the RecordSet. As an example, consider a RecordSet with the cursor position pointing to the first item. After calling GetRows with a three (3) for the first parameter, the next time you read the RecordSet the cursor will be pointing at the fourth record.

Unfortunately, I was caught out by this feature. Without consulting any documentation on the method first, I expected that calling GetRows would copy an arbitrary number of records from any position in the RecordSet without altering the current cursor position. If it did need to move the cursor to access the rows, I expected that it would return the cursor to the original position.

This is really just a fine implementation issue. I felt that since it was a copy type method, that it wouldn’t have made any modification to the RecordSet object. If you hadn’t of read the documentation, would you expect that it would advance the cursor or leave it in its original position?

Select, Option, Disabled And The JavaScript Solution

As I mentioned recently, there is a bug in Internet Explorer that stops you from disabling options in a select/dropdown element. At the time, I felt this was quite poor so I set about finding a solution. For the impatient among us, you can step straight to implementing it if you want.

Unsuccessful Ideas

In an attempt to save everyone else some time, I’m going to list the different ideas, methods and combinations of, I attempted that were unsuccessful:

  1. Attempt: use the CSS pseudo :hover against the <option> element.
    Problem: Internet Explorer doesn’t support the :hover pseudo class on arbitrary elements.
  2. Attempt: Wrap the contents of the <option> element in an anchor and use the :hover on that instead.
    Problem: The <select> tag is considered a replaced element, which means the tag is replaced with your operating systems equivalent. As a by product, no other HTML element is valid within the <option> tag.
  3. Attempt: Use the JavaScript onmouseover and onmouseout events on the <option> element to make the element appear as though it was disabled.
    Problem: Internet Explorer doesn’t support the onmouseover and onmouseout events against an <option> element.
  4. Attempt: Use the JavaScript onclick event on the <option> element to check if the disabled attribute has been applied, act accordingly if it has been.
    Problem: Again, Internet Explorer doesn’t support the onclick event againt the <option> element.
  5. Attempt: Use the JavaScript onclick event against the <select> element, to again check if an <option> has the disabled attribute in use.
    Problem: Internet Explorer doesn’t support the onclick event against a <select> element.

Successful Ideas

The solution to this problem is comprised of two parts. Firstly, knowing when you make a selection or change the current selection. Secondly, keeping track of the current selection, so you can revert to it in case the user selects a disabled option in the list. If those two things can be achived, then we can emulate the disabled attribute on an option element

Part 1
You can get around not having an onclick event against the option element by using an onchange event against the select. Knowing when you click an option is mandatory, as it lets you know when/if to check that the selected option is disabled. This is taken care of, we can move on.

Part 2
Next up is keeping track of the ‘currently selected’ item. Generally, the first tool in the chest that most people reach for in this case is an onclick event. However, since we’re working with a browser that doesn’t implement those events on the element(s) in question, another solution was needed. The next event that would match what we want to do is onselect, however it isn’t implemented in IE either. Thankfully, the onfocus event is our savior.

How It Works

First thing is making sure that the code only executes on the correct browsers. You could use browser sniffing techniques or proprietary JavaScript functions to isolate IE, however that can be inconsistent. Since we’re targeting IE, it seems more than reasonable to use a conditional comment. In case you are unfamiliar with them, a conditional comment looks like a standard HTML comment to every non-IE browser; however IE interprets them and allows the author very simple conditional testing. We’re going to use this simple testing to include an external JavaScript file.

If the JavaScript does execute, it checks to see if you have any <select> elements in the page. If you do, it iterates through them, attaching an onchange and an onfocus event to each one. At the same time, the disabled option elements (if there are any) are also highlighted with the disabled text colour.

At this point, you have nothing else to do. The onload event and the two functions will do everything for you from this point. The one caveat is if you are manipulating the disabled attributes on the options through the DOM. In which case, you do have to call the emulate function, passing into it a reference the <select> you are manipulating.

The JavaScript

To make this work, an event and two functions are used. They are listed here so you can glance over them:

  1. window.onload = function() {
  2. if (document.getElementsByTagName) {
  3. var s = document.getElementsByTagName("select");
  4. if (s.length > 0) {
  5. window.select_current = new Array();
  6. for (var i=0, select; select = s[i]; i++) {
  7. select.onfocus = function(){ window.select_current[this.id] = this.selectedIndex; }
  8. select.onchange = function(){ restore(this); }
  9. emulate(select);
  10. }
  11. }
  12. }
  13. }

The restore function returns the selected item to its previous selection, if the newly selected item is disabled.

  1. function restore(e) {
  2. if (e.options[e.selectedIndex].disabled) {
  3. e.selectedIndex = window.select_current[e.id];
  4. }
  5. }

The emulate function changes the font colour of all options in a <select> element with the disabled attribute set. The colours used on lines 4 and 7 are CSS2 colour names, which are considered system colours. System colours reflect what your current computer settings are, so they should change with your current desktop theme (at least that is my interpretation of it).

  1. function emulate(e) {
  2. for (var i=0, option; option = e.options[i]; i++) {
  3. if (option.disabled) {
  4. option.style.color = "graytext";
  5. }
  6. else {
  7. option.style.color = "menutext";
  8. }
  9. }
  10. }

Implementing

Using this script is meant to be as simple as possible. All you have to do is download the external JavaScript file. Upload it to your site and place a single conditional comment in your HTML, such as:

  1. <!--[if lt IE 7]>
  2. <script type="text/javascript" src="select-option-disabled-emulation.js"></script>
  3. <![endif]-->

Examples

Following are some simple examples to display what Internet Explorer renders at the moment, through either html/xhtml/quirk/compliant states. There are also two examples of how the script functions as well, simple but they demonstrate it none the less.

Follow Up

After this post being active for over a year now, it continues to draw in consistent traffic from around the internet. Even though this was a proof of concept and not a complete solution, it has saved many people a lot of time. Plenty of people have taken the basic idea I started with and extended it, which I think is fantastic. Recently, a couple of people have sent through comprehensive techniques which are either built on my initial work in some way or inspired by it. These solutions are out perform my simple proof of concept, so they are definitely worth noting for everyone to use:

  • Apptaro created an elegant solution using a DHTML Behaviour file. These behaviour files only execute in Internet Explorer which is a great way isolating it from interfering with other web browsers.
  • Kaleb Walton has implemented a JavaScript object oriented version of my proof of concept. Kaleb’s version implements the fix for a standard dropdown, a listbox and a multi-select listbox.

Both of the above examples are excellent, so you should pick which ever you feel is best going to suit your needs.

Disable Option’s In A Select (Dropdown) Element

The follow up article, Select, Option, Disabled And The JavaScript Solution has since been published. Please refer to it for more comprehensive information.

You would expect that being able to disable an option in a <select> element (read: dropdown box) would be a fairly important feature for a browser vendor to implement. From a Human Computer Interaction (HCI) standpoint, it is vital – as it lets the users know the option is exists, however under the current circumstances it is temporarily unavailable.

According to the W3C specifications for HTML4, there is an attribute available for both the <select> and <option> elements, which has the desired effect. The attribute in question is disabled (scroll down a little bit to see the option attributes).

According to the above specifications, you should expect that if you apply the disabled attribute to either a <select> or an <option> element, that it would become unavailable. If applied to the <select> element, the entire dropdown list will be greyed out and not selectable. If only applied to the <option> elements, the dropdown may be selected, however the options which are disabled will be greyed out, not selectable and focus will slide over them should you navigate through the options with the keyboard. The guidelines are very clear what is to be expected by this attribute.

Following is a small code snippet of how it should be implemented:

  1. <form action="form.asp" method="post">
  2. <select id="dropdown" name="dropdown">
  3. <option value="cat">Cat</option>
  4. <option value="snake" disabled="disabled">Snake</option>
  5. <option value="spider" disabled="disabled">Spider</option>
  6. <option value="dog">Dog</option>
  7. </select>
  8. <input type="submit" value="submit />
  9. </form>

You can use two variations on the syntax for the disabled attribute, depending on the version of HTML you are targeting:

  1. HTML4: <option value=”spider” disabled>Spider</option>
  2. XHTML: <option value=”spider” disabled=”disabled”>Spider</option>

The rendering of the above code snippet and the disabled select should be comparable to the below screenshots:

Compliant rendering of a disabled option element Compliant rendering of a disabled select element

This is where everything starts to slowly fall apart. The major browsers that are in use today are IE6, IE5.5, Mozilla/Firefox, Opera, Safari, OmniWeb. Of those, IE6 is without question the most used browser around the world. This strikes a problem for web developers, as its support for the new web development techniques (read: CSS1, CSS2 and soon CSS3) are either not present at all or worst yet, present but implemented incorrectly.

It never ceases to amaze me how a browser like IE6, managed to not implement something as trivial as an attribute like disabled. The IE team managed to implement it against the <select> element, but some how overlooked the <option> element. They implement the readonly attribute against the appropriate elements – yet some how the disabled attribute managed to be overlooked when they implemented it. More surprising is that, since the HTML4.01 specification came out in late 1999, IE has been updated and upgraded for various things literally hundreds of times. Why hasn’t this made it into an update? You’d begin to think that Microsoft aren’t aware of it, however the thought of that just seems too far fetched.