IE8 has a right table border problem on JavaScript-inserted cells

If you use collapsed table borders on with IE8 and insert or delete cells in the table with JavaScript, the right border will be missing. For example, when you insert a row in a table this CSS ...

.fmtTable { border-collapse: collapse; width: 100%; border: 1px solid #D0BFAB; }

... with the following jQuery code ...

$("<tr><td colspan='2'>Test</td></tr").insertBefore("table.fmtTable tr:last");

... the right border will disapper.

Fix: declare an extra class last ...

table.fmtTable .last { border-right: 1px solid #D0BFAB; }

... and apply it to every last cell in the table:

$("table.fmtTable tr").find("td:last").addClass("last");

Another XSLT-related bug in IE

I’ve created an RSS feed that points to various web pages that use client-side XSLT (read this article if you’re not familiar with the architecture of my web sites). The feed is accessible through FeedBurner which modifies the feed slightly to track clicks:

  • All the links in the feed are modified to point to FeedBurner URLs
  • The FeedBurner URLs encode the actual click destination (this allows FeedBurner to count the clicks)
  • FeedBurner uses “301 Moved Permanently” status code to redirect the user to the target web page.

When the target web page is an XML document with xml-stylesheet directive, Firefox and Chrome display it correctly, but IE 8 crashes, as it interprets the XSLT stylesheet address relative to the “old” location (FeedBurner), not the redirected location.

I could fix this problem by hard-coding absolute XSLT URL in the XML document, but then some browser might consider that a potential CSS attack, causing further problems. For the moment, IE 8 has proven to be closer to Firefox and its XSLT woes that I thought.

OMG, more browsers are coming

The EU commission has reached an interesting agreement with Microsoft: Microsoft will present European users with a choice screen allowing them to select one of many browsers as their default browser. In principle, this is a great idea, if they could decide to offer users three or four browsers; very probably the users will have 10+ choices.

While this is supposedly good for users (and excellent for niche browser vendors), increased market share of currently irrelevant browsers might spell trouble for web developers using non-mainstream technologies (my favorite example: client-side XSLT transformation). For example, the percentage of users not using Firefox, IE or Chrome (yes, in that order) on one of my web sites is well below 5%, so I don’t care too much whether every little details works as it should. The situation would change drastically if they “minor” browsers would represent 20% of my users.

Custom data in HTML5 tags

Quite often I’d like to add application data to my HTML markup to pass information between server-side scripts generating the HTML markup and client-side jQuery scripts. Prior to HTML5 you could decide to use XHTML and your private namespace; numerous applications (including Facebook and my web sites) use this approach. It works nicely unless you’ve decided to use client-side XSLT transformation in Firefox.

HTML5 gives you another option: embedding custom non-visible data in HTML tags. You can add as many attributes as you wish to a HTML tag as long as they start with the data- prefix. HTML5 compliant browsers will eventually give you DOM access to these attributes through the dataset attribute; in most browsers (ancient IE or Netscape releases might not work) you can get these attributes with the getAttribute (or jQuery attr) call.

You might wonder what the difference is between using non-standard attributes of your choice and standard data- attributes as long as the browsers don’t support the dataset property. If nothing else, your HTML code will be validated by HTML5 validator.

Find Facebook Friends with Your Facebook Connect Application

InformIT.com has just published the last article in my Facebook Connect series. This uses the common task of finding the Facebook friends of your Facebook Connect user to explain the intricacies of FQL (Facebook Query Language).

Create client-side charts with Highcharts

I’ve stumbled across a Highcharts announcement on ajaxian.com a few days ago. Highcharts looked like something I’ve been (passively) looking for for years: a simple tool that could take values generated by the server and turn them into a fancy graph. It lived up to the promise: after struggling with it for a few hours, I’ve deployed my first chart-on-a-page to production (note to myself: still have to fix the caching issues).

The tool works great, but there are (as always) a few hidden gotchas:

  • The reference manual gives you all the information, the How to use page is somewhat cryptic.
  • The demo pages show you incomplete code; all the formatting parameters are missing.
  • Although it’s obvious in the hindsight, the documentation “forgets” to mention that you have to style all the elements of the graph, otherwise you’ll get a nice white-on-white nothingness. You can dig through the demo code to find the routines that do that (they’re hidden in a JavaScript file) or look at my code.
  • Another missing bit: if you want to apply the same format to multiple graphs, set the default options with the Highcharts.setOptions(chartFormat) call.
  • Last but not least: the series parameter is an array of objects (each object having at least the data property). If you read the documentation too literally and define series as an object (not array), you’ll get a nicely formatted empty canvas (assuming you’ve got the formatting parameters in place).

A nasty Firebug “surprise”

If you happen to believe that the client-side XSLT transformations are a good thing (I am firmly footed in that camp), Firefox 3.x brings nothing but disappointments. Now it's Firebug's turn: they’ve managed to mangle the console.log function. It worked a while ago, but then a brilliant mind decided to re-implement it with a hidden DIV between the HEAD and the BODY element:

<div id="_firebugConsole" style="display: none;" FirebugVersion="1.4.5"/>

This DIV is created automatically for regular (X)HTML pages, but not for XSLT-generated content, so the output of console.log gets sent to /dev/null (plus you get loads of weird error messages).

Publish stories on Facebook

In my first Facebook-related article published by InformIT, I’ve described the basics of Facebook Connect – a JavaScript API that can connect your web application with millions of Facebook users. The next step is pretty obvious: once you’ve attracted the Facebook users, it makes sense to publish their activity on your web to their Facebook news feed. The process is described in my next InformIT article “Publish Your Application Stories to Facebook”.

jQuery event delegation

A new article published on the Learning jQuery blog explains the intricacies of event delegation and the new .live() jQuery method. The event delegation (a great feature) allows you to declare a single event that works on numerous children of the same parent (instead of binding a copy of the event-handling function to every child).

The .live() method goes a step beyond that and declares an event for every element matching its selector. However, the implementation of the .live() method is resource-consuming: it binds an event handler to the document root, so it’s involved every time the specified event occurs anywhere in the document.

Use Facebook Connect to Bring Your Application to Millions of Users

Almost a year ago, I’ve joined Facebook which has at that time rolled out the initial sandbox of the Facebook Connect environment. I’ve developed a very simple application and waited for the FB Connect rollout. A few months later (around December 2008) they got so far and I’ve deployed my application on my production server … only to get user complains a while later telling me the application has stopped working.

It turned out Facebook has (somewhat silently) changed their API enough that it broke my code. However, I only had to fix a few functions to adapt them to a now better-documented API. I’ve also used a few extra bits-and-pieces Facebook engineers threw in after discovering what we really need. The second FB Connect experience was so good that I’ve decided to write a series of articles for InformIT describing how you can integrate your web site with Facebook. The first one, Use Facebook Connect to Bring Your Application to Millions of Users, has just been published on the InformIT web site.

Learning jQuery book from Packt

When I’ve decided to start using jQuery, I bought a number of books to help me get started (my time is way too valuable to be spent on Google wild chase), including the jQuery Reference Guide from Packt. In the meantime they’ve published Learning jQuery 1.3 covering the latest major release of jQuery.

I’m waiting for my review copy from Packt (then I’ll be able to tell you more about the book) and they were kind enough to provide a link to a sample chapter that I can share with you.

Introduction to RDFa

I’ve finally found time to read the RDFa articles published on A List Apart. I have to digest the information and try to figure out whether it’s relevant to my web sites, but I’m already intrigued enough to publish the links for future reference:

Ajax with jQuery

The third jQuery article I wrote for InformIT covers the jQuery Ajax support. It describes simple Ajax calls that insert HTML fragments into the current web page, processing of XML responses, and global AJAX events that display the loading indicator.

My second jQuery article: refactoring a web page

When I’ve decided to switch from X library to jQuery, I was faced with tons of (now outdated) pages in my web site that I had to migrate to jQuery. As it turns out, doing the migration job properly is a great idea: armed with the CSS experience (and believing in the need for using tags that make sense) I was able to make compact, more readable and better degradable (an awful word to use in this context) web pages.

I’ve described some of the lessons I’ve learned in this process in the Web Page Refactoring with jQuery article that was published by InformIT.

XSLT: Truncate text with ellipsis

A great set of XSLT templates that allows you to truncate XHTML markup (or any XML node) at specified text length. I was impressed ;)

Firefox 3.5 XHTML support stinks

Continuing my Firefox “quality” rants: I just found the willpower to completely redesign my AJAX framework, going from IFRAMEs to jQuery AJAX calls (replacing straightforward and quite elegant XSL transformations with pages of convoluted JavaScript code) to work around the bugs in FF3.0, only to find out that FF3.5 is even worse and introduced numerous additional “features”.

For example, FF3.5 requires an explicit </script> tag within an XHTML document with proper DOCTYPE. The following document was validated with W3C XHTML validator …

<!DOCTYPE html 
  PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
  <head>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
  <title>Test</title>
  <script src="… source URL … " type="text/javascript" />
</head>
<body id="body">
</body>
</html>

… but it does not load the script in FF3.5.

Before anyone starts telling me that it’s not so hard to include the closing </script> tag in your source – try telling that to the database with native XML support where I’m storing snippets of the code. I had to convert the field from XML to TEXT (and lose all XML goodies I might eventually get) just to avoid the elimination of the explicit closing tag.

May I make a quick suggestion to the FF developers: maybe, just maybe, you might want to consider supporting existing web applications in parallel with adding new features that not too many people can use (because no other browser supports them yet).

JS-Kit crashes a Blogger blog in Internet Explorer

Several times I’ve stumbled across Blogger-hosted blog that simply refused to open in Internet Explorer with the “Operation aborted” pop-up window and subsequent error page. I never tried to investigate what was going on (I simply copied the URL into another browser), but when I’ve installed JS-Kit on my blog, I’ve started getting the same problems … obviously a cause for a major alarm.

The Infinities Loop site provided an answer in the comments: a SCRIPT performing specific manipulations should be a child of BODY, not another HTML element. When I’ve moved the JS-Kit script (<script src='http://js-kit.com/extra/blogger/comments.js' type='text/javascript'/>) from the Blogger widget to the end of the page, the new fanciful JS-Kit-based comments worked flawlessly.

Introduction to jQuery article published by InformIT

After becoming a convert (and a somewhat quiet evangelist) to jQuery, I wrote a series of introductory articles for the InformIT.com web site. The first one, Introduction to jQuery, covers the basic concepts, including selectors, chaining, and the page ready event. It also contains a comparison between a “traditional” JavaScript code and jQuery code.

Refactoring a menu: Remove unnecessary IDs

If you’re new to this series, read the “Refactoring a simple menu” and “Remove inline CSS” first.

The original HTML code for the dropdown menu (see below) was full of IDs that were used as a DOM navigation tool (I’ve used getElementById instead of traversing the DOM tree). When moving from a simple wrapper JavaScript library (I was using the X library) to jQuery, it makes sense to use its powerful traversal functions to replace the ID-based navigation.

<div class="rowMenu" id="IDAHYJQB">
  <p><a href="/climbing/myClimbs/myClimbs.asp">First page</a></p>
</div>
<div class="rowMenu" id="IDAKYJQB">
  <script>menuRegister('IDAKYJQB')</script>
  <p id="IDAKYJQB_main"><a href="javascript:menuClick('IDAKYJQB')">Add ...</a></p>
  <div id="IDAKYJQB_sub">
    <p><a onclick="menuSelect('IDAKYJQB')" 
        href="/climbing/myClimbs/myClimbs_add.asp">New entry </a></p>
    <p><a onclick="menuSelect('IDAKYJQB')" 
        href="/climbing/myClimbs/myClimbs_editWall.asp?a=add">Edit</a></p>
    … more …
  </div>
</div>

The HTML code is interspersed with inline calls to three JavaScript functions:

  • menuRegister registers the ID of a drop-down menu
  • menuClick opens a drop-down menu
  • menuSelect hides the drop-down menu and

Today we’ll replace these functions with simpler jQuery equivalents while getting rid of element IDs.

The menuRegister function will not be needed once we fix the DOM traversal problem. The menuClick and menuSelect functions will be merged into a single menuClickEvent function that will identify whether it works on a main menu entry or an entry of a drop-down menu. The this variable will be passed to the menuClickEvent function to avoid any ID-based references.

The menuClickEvent function has to perform a few setup tasks:

  • Get the DOM element that was clicked, using either the function parameter or (for future use) the value of the this variable.
  • Get the parent paragraph.
  • Decide whether it’s operating on a top-row entry (the parent paragraph has a DIV sibling) or not.

Using jQuery makes the job extremely simple:

function menuClickEvent(thisParam) {
  var a = thisParam || this; 
  var p = $(a).parents('P:first');
  var d = p.siblings('DIV');
  var toprow = d.length != 0;

  … rest of the code …
}

If the menuClickEvent function works on an element of a drop-down menu, it should hide the drop-down menu and return true (indicating that the event handler should perform its default task), otherwise it should toggle the state of the down class of the current paragraph and the visibility of the sibling DIV. The jQuery-based code is much shorter, more elegant and way more readable than the original.

function menuClickEvent(thisParam) {
  var a = thisParam || this; 
  var p = $(a).parents('P:first');
  var d = p.siblings('DIV');
  var toprow = d.length != 0;

  if (toprow) {
    p.toggleClass('down');
    d.toggle();
    return false;
  } else {
    p.parents('DIV').hide().siblings('P').removeClass('down');
    return true;
  }
}

With the new jQuery-based implementation of the drop-down menu, we can get rid of all element IDs, resulting in much shorter HTML code:

<div class="rowMenu">
  <p><a href="/climbing/myClimbs/myClimbs.asp">First page</a></p>
</div>
<div class="rowMenu">
  <p><a href="#" onclick="menuClickEvent(this)">Add ...</a></p>
  <div>
    <p><a onclick="menuClickEvent(this)" 
        href="/climbing/myClimbs/myClimbs_add.asp">New entry </a></p>
    <p><a onclick="menuClickEvent(this)" 
        href="/climbing/myClimbs/myClimbs_editWall.asp?a=add">Edit</a></p>
    … more …
  </div>
</div>

Next task: remove inline JavaScript calls

Opinion: Is the Firefox development model really better than Microsoft’s?

Everyone loves bashing Microsoft and preaching the vast superiority of Firefox over IE, particularly its near-perfect implementation of W3C standards. Unfortunately, that might be true as long as you’re doing what the most vocal advocates (the CSS folks) are doing, if you happen to rely on some other “supported” standard, you might find yourself in deep ****.

As my regular readers know, I happened to make a decision to use client-side XSLT a while ago. From the technology standpoint, it was a perfect solution … until Firefox 3 came out. It has so many XSLT-related problems that it’s almost impossible to get the right combination of relevant parameters to have the same XSLT stylesheet working on Firefox, IE, Chrome and the web server (for non-XSLT-capable clients).

OK, one would understand that every major software project has bugs. But it’s hard to understand that so many of the XSLT bugs are untouched after several years. For example: generic ticket describing XSLT result document problems (4 years), HTML-DOM initialization issues (5 years), Firefox crashing when combining XSLT with document.write (6 years), Firebug not working on XSLT-generated pages (1,5 year).

I’ve heard all about limited resources and priorities in my “previous life”, but let’s face the reality: once the motivation (let’s beat IE) wears off and the platform accumulates years of old sins and bad decisions, the development model doesn’t matter. Firefox is becoming no better than IE.