Tag Archives: Browser differences

The jQuery UI CSS Framework – Part 2: How To Create Widget-style Boxes

This is the second post in a series on the jQuery UI CSS Framework.    Here’s the first one.

Today I’ll show you how to create a nice looking box that has sort of a widget appearance to it. The jQuery UI components already provide similar functionality. For example, the Dialog Box is quite pretty, and you can easily make it modal or not.  But frequently we want to make a box for content somewhere on a page- much like the sorts of boxes that appear on WordPress blogs, Drupal sites or iGoogle, for example.  The jQuery UI CSS Framework comes with selectors that make this easy. Also, remember that one of the benefits of the UI framework is that you can easily change the theme of your site, without having to touch any markup or CSS – you simply change the path of the external theme css file to point to another directory. Again, the examples I’ve made use the Redmond theme.  Here’s the markup for a simple box with a nice heading:

<div id="mybox" class="ui-widget ui-widget-content ui-corner-all" style="margin-top:20px; width:300px; height: 150px;">
  <h3 class="ui-widget-header">Weather Widget</h3>
  <p><span class="ui-icon ui-icon-comment" style="margin: 0 2px 0 2px; float:left;"></span> Tomorrow it will be light during the day, and dark at night.</p>
</div>

It’s rendered (in FireFox) like this:

weatherwidget

As you can see, the markup is pretty simple.  I’ve given the container  div an arbirtrary width and height. You might want to specify  a width, but omit the height s that the div just stretches with your content.  Let’s look at the classes used for the div, the heading (h3) and the image respectively:

The div tag:    The class  .ui-widget  ensures we use  a consistent font family and size for the content inside it. It also applies the 1.1em rule. Combined with the css selector :    body {font-size: 62.5%} this initially yields a font size of 11px at typical screen resolutions. This whole 1.1em thing can be a bit of a problem, as I’ve discussed in other posts. For example, if I embed another container using the same selectors, my text comes out at 12.1px (1.1x 1.1em).  You can inspect your element with Chris Pederick’s Web Developer plugin for FireFox to see bad behavior at work. For example, see below:

Font size for second container text is now 12.1px, not 11px.

Font size for second container text is now 12.1px, not 11px.

I ran into this in an app where I had tabs embedded inside tabs. The jQuery UI code applies the .ui-widget class to tabbed content containers behind the scenes, so I ended up with oversized text compared to the rest of my page.

The class of .ui-widget-content applies the border, along with some padding. the .ui-corner-all selector gives us rounded corners (in FireFox and Chrome, not IE).

The h3 tag: This uses the class  .ui-widget-header. This is pretty self explanatory. It applies a nice background on white text (based on the Redmond theme) to our heading. You can use this class on other tags, too. For example, I use it on tr tags for my table heading rows.

The image (span) tag: (.ui-icon and .ui-icon-comment).  I just threw this in as a bonus for this lesson. jQuery UI is very clever at handling icons. Instead of having a whole bunch of images, you basically have one big image sliced into squares, with each icon class being a small window over the appropriate square. This is a variation on the famous Sliding Doors sprite concept at A List Apart.  It saves different image resources having to be loaded, to optimize performance. It also allows the icons to be themed easily, because you don’t have to change the path for an image, as you would for a typical HTML img tag. You can also apply a hover state to any icon in the set, simply by setting the class to .ui-state-highlight.  We’ll cover this in more detail in a later article.

In this case, I used a span tag to display the comment icon. This could also be an anchor tag, or a li tag, or whatever.   The .ui-icon class gives us a 16 x 16 pixel area blocked out for whatever icon we choose. The .ui-icon-comment class displays a comment icon (similarly, .ui-icon-trash shows a trash can, etc. etc.). You can see the entire set of available icons at the Themeroller page.  The default setting for .ui-icon is display:block, which forces a line break, which is why I had to add an inline style setting of “float: left” to get it to appear on the same line as my text.

That’s it!  the next article will show you how to style pretty forms elements with the framework.

The jQuery UI CSS Framework – Part 1: Intro and How To Style a Button

This is the first in a series of articles on the jQuery UI CSS Framework.. This is a powerful suite of CSS selectors that you can use to build web applications with a consistent UI. The main jQuery UI demo page shows you a list of UI widgets (which are still somewhat limited in scope compared to ExtJS, for example), but it doesn’t do a very good job on selling you on the benefits of designing other UI components, or components of those widgets, using the UI CSS framework. In this article I explain the framework, its benefits and weaknesses, and show you one simple example of styling a button.

What is the jQuery UI CSS Framework?

It is a set of CSS selectors that let you design your web pages to conform to the jQuery UI widgets standards. Quote:

The jQuery UI CSS Framework provide semantic presentation classes to indicate the role of an element within a widget such as a header, content area, or clickable region. These are applied consistently across all widgets so a clickable tab, accordian or button will all have the same “ui-state-default” class applied to indicate that it is clickable.

(from the jQuery UI Theming documentation page).

Benefits of the jQuery UI CSS Framework

Here are the top benefits I think the framework has to offer:

  • It handles difficult design issues for you. For example, you can apply rounded corners to buttons and links easily, just by adding a class of  “ui-corner-all” to your element.
  • It gives you a consistent look and feel to your page design elements
  • You can use the jQuery UI widgets (such as tabs, dialog boxes, accordions, etc. in conjunction with your own custom elements (text, tables, buttons, boxes, icons, etc.) and get the same look and feel for both.
  • The UI is skinnable. You can use Themeroller to roll your own theme, or select an existing theme. For example, I’m using the ‘Redmond’  theme in an application I’m currently building. You can see the Gallery of themes by clicking the ‘Gallery’ tab in the top left corner.  The gallery also shows you what the standard jQuery UI widgets look like. Unfortunately it doesn’t show you other common design elements- but that’s why I’m blogging!
  • You can easily switch to another theme just by changing a single path reference in your applications. You can see this at work by using the Themeswitcher widget, which is easy to embed in your page (just remember you will be connecting to the jqueryui.com website when you use this widget).

Downsides to the Framework

The framework is not without its weaknesses, some of which, over time, I’m sure will be addressed. The major ones I see are:

  • Poor documentation of the purpose behind each selector.  For example:

    .ui-helper-clearfix: Applies float wrapping properties to parent elements

    . What exactly does this mean? And where would you use it? I think I’ve figured it out, by trial and error, but couldn’t the authors write something more meaningful?

  • Reliance on em as the unit of measure rather than pixel. I realize there are lots of advantages to this, but it has its drawbacks too- most notably, when you nest some UI elements you can end up with different font-sizes, due to the use of 1.1em in some cases (this is a multiplier, so in my app I have 1em applied, which results in a font size of 11px, then I have a tab with content. The text in that content comes out at 12.1px (1.1em). If you don’t understand em versus px, try this article. Also, see my post on using 62.5% on a body CSS selector..
  • Incomplete framework. Most notably, tables are not addressed. (I use tables to present database information in business apps). Tables fall outside the regular cascade rules, it seems, so the font size for table content is screwed up. I suggested a simple fix of adding the word ‘table’ to a selector, but that got dismissed as too specific. So whenever you use a table in conjunction with the Framework CSS, you’ll have to add a customized CSS rule, such as this one:
    .ui-widget table { font-family: Lucida Grande, Lucida Sans, Arial, sans-serif; font-size: 1em; }. I could rant about this, and may do in another post… Other selectors are missing, too, such as alternating row colors for table zebra striping. Perhaps they will add this to the Themeroller app, as well as to the CSS Framework API specifications.
  • Sometimes you need other CSS to make things look like they do in the online examples. I ran across this with the Dialog example that shows a form. The form looks really beautiful, but it actually uses several additional selectors besides the ones included in the Framework CSS.  I don’t really think there’s much of a technical alternative here, but it’s something you need to be aware of.

How To Learn About The Framework

I learn about how to use the framework by using the following strategies:

  • Read the official CSS Framework documentation.
  • Try out the widget examples and do a ‘View Generated Source’ or ‘Inspect Element’ with Firebug. This shows you how the UI Widget developers utilized the CSS framework. For example, I noticed that the Dialog widget shows really nice looking Ok and  Cancel buttons, so I inspected them to see which CSS rules had been used. (See my example below).
  • Follow the jQuery UI forum and read books. There’s a new edition of a book on jQuery UI 1.7 that recently (Nov 2009) came out.

Example Using the Framework To Style a Button

Here’s a simple example of using the CSS selectors to style a button. I’m using the Redmond theme here.

I assume you know how to install the jQuery UI library and CSS.  You can grab it here.

Here’s the code:

    <style>
    body {font-size: 62.5%}
    </style>
<button id="cancel" type="button"  class="ui-state-default ui-corner-all">Cancel</button>

Here’s what it looks like:

jQuery UI button in FireFox

jQuery UI button in FireFox

jQuery UI button in Chrome

jQuery UI button in Chrome

jQuery UI button in IE

jQuery UI button in IE

As you can see, FireFox and Chrome each do a nice job of rendering the rounded corners, while IE 8 still doesn’t support this feature (at least, not with CSS).

Explanation of The CSS

I’m using two classes on the button element. This is a common coding technique when using the jQuery UI CSS framework. It results in combining the various selectors of each style in an accumulative manner. The ui-state-default class “Applies “clickable default” container styles to an element and its child text, links, and icons.” For example, we could apply this to a link and get essentially the same effect. This class includes a background image that provides the button coloring. As I mentioned earlier, if you change the theme used in your app, the button will appear in the color of that theme.

The ui-corner-all selector applies a radius (rounded corner) to each of the four corners of the button border. That’s it!

Next Article

In the next article I will show you how to style a div to create a nice looking box with a heading in it.

Checked attribute of checkboxes- IE versus FireFox

In FireFox, <input type="checkbox" name="checkme" value="ok" "checked"> results in the checkbox being checked by default. In IE (version 7 – haven’t tried 8), it does not. This is one of the few times FireFox is more liberal than IE, and wrong. The correct code is: <input type="checkbox" name="checkme" value="ok" checked="checked">

See this W3C specification.

It’s a bit difficult to find the rule on this page, but if you scroll down to section 17.4 The INPUT element you’ll see this text for the checked attribute:

checked (checked) #IMPLIED — for radio buttons and check boxes —

Even then, it’s still confusing, because if you click the link for the ‘checked’ attribute, you’ll see it referred to as ‘this boolean attribute’. While it’s correct that it is a switch – either “checked” or nothing, it’s not a true boolean – either ‘true’ or ‘false’. Anyway, this one bit me because I wrote some markup with checkboxes and only tested the page in FireFox. In my test, all the checkboxes were checked, by default, which is what I wanted. The IE users got a different result altogether.

Update: Chrome also requires that you use the correct (strict) syntax.

How To Create A Global Event Object For Both IE and FireFox

How To Create A Global Event Object For FireFox and IE

Disconnecting Behaviour from Content

Recent articles on Javascript recommend separating content from behaviour, much the same way as you should separate content (HTML) from layout (CSS). This means registering event handlers for page elements at the script level rather than attaching code to specific elements. This is a great idea, and one which all of us Javascript coders should adopt. Also, your scripts should be cross-browser compliant, at least for IE and FireFox. This post explains how to handle events that are attached to specific events in a manner that provides IE and FireFox compliance with minimal changes to your script.

Here’s an example of a behaviour that is too closely tied to content:

  <input type="test" name="phone1" onclick="editphone();">

To separate content from behaviour you can code this inside the <head> portion of your page:

<script>
// Use this instead of <body onload="init();"> :
window.attachEvent('onload', init);

function init()
{
  document.getElementById('phone').attachEvent('onclick',doSomething);

}
</script>

Then, the input tag looks like this (sans the onclick attribute):

	<input type="test" name="phone"  id="phone" >

(this is IE compliant code – see Quirksmode Advanced Event Handling for cross-browser solutions).

You can also add an event handler for your entire document, so you can trap a given event such as click for any element on your page:

 document.attachEvent('onclick',  dosomething);

The dosomething function can then check the element on which the event occurred, and take appropriate action, like so:

function dosomething(e)
{
// get handle to object event occurred on:
  var EventObj = window.event.srcElement;
  if (EventOjb.id == 'phone') alert('You clicked on the phone number');
  // etc...
}

This is also an IE-specific solution, and PPK explains in detail how to code for both FireFox and IE.

Unobtrusive Solution For Existing Closely Linked Presentation-Behaviour Markup

This is all well and good if you use advanced event handlers as described above. But what if you have a bunch of legacy HTML and script that uses event handlers that are attached directly to the content? It turns out this presents problems for FireFox. First, I’ll show the problem, then present a solution that works for both.

The Problem

For example:

<a  id="link1' onClick="youclickedme('newpopup1');">Click me!</a>

In this case, the function “youclickedme” is supposed to be a function that can be called by any number of elements on the page. It expects a parameter that is unrelated to the link itself. So what if you want to know what element the onclick event happened for? Consider this script:

function youclickedme(parm1)
{
 if window.event.srcElement.id = "link1"   // do something.
}

Here we are able to detect the object the event occurred on because IE has a global variable called event that is available anywhere in your code. FireFox, on the other hand, has no such global variable. Instead, it uses a local event variable (e) that is populated when an event that is registered is triggered. So, borrowing from PPK at Quirksmode, here’s a cross-browser function to detect the type of an event:

function doSomething(e) {
 if (!e) var e = window.event;
 alert(e.type);
}

This function checks to see if a local event object has been created and passed to the event handler, which it will be in FireFox. If e is not defined, then the function assumes the IE global event variable window.event exists.

The lack of existence of the global variable window.event means the “youclickedme” script will fail in FireFox. Also, there is no easy way to get the event without major restructuring of code. However, there’s a relatively simple and elegant solution that creates a global event variable for FireFox that emulates the widow.event variable.

Using FireFox’s Event Capturing Model

FireFox uses an event capturing model that percolates events down from the containing element to contained ones. (IE uses event bubbling. Again, see Quirksmode for a detailed explanation). The event-capture model lets us attach an event handler at the document level and unobtrusively perform some function.

Creating A Global Event Variable For FireFox and IE

Because this happens before element-specific events, it means we can use this model to set a global variable that serves the same purpose as IE’s window.event variable.
It then becomes a simple matter of substituting that variable for window.event throughout our script in order to make element-specific event-handlers work. Here’s cross-browser compliant code:

// Attach an on-click event handler at the document level:
xl_AttachEvent(document, "click", xl_FFEventhandler);

// Event handler for any onclick:
function xl_FFEventhandler(e)
{
 // Declare a global variable to trap events in FireFox or IE
 ff_event  = null;
 ff_event = xl_GetEvent(e);

}

That’s it! Here are the helper functions, from PPK’s work at Quirksmode.

function xl_GetEvent(e)
{
 // e gives access to the event in all browsers
 if (!e) var e = window.event;

 return e;
}

function xl_AttachEvent(obj, evType, fn, useCapture)
{
 if (!useCapture) var useCapture = true;
 if (obj.addEventListener){
  obj.addEventListener(evType, fn, useCapture);
  return true;
 } else if (obj.attachEvent){
  var r = obj.attachEvent("on"+evType, fn);
  return r;
 } else {
  return false;
 }
}

Change “youclickedme” function to be cross-browser compliant

This is all we need to do to change function “youclickedme”, our event handler that is attached via the onlcik property of the element:

 if ff_event.srcElement.id = "link1"   // do something.

Well – not quite, since srcElement is IE-only, while FireFox uses target instead. But you get the idea. For example, here’s a cross-browser function to return a handle to the element the event occured on- a modified version of PPK’s using this technique:

function xl_eventTarg()
{
 var targ = null;

 if (xl_event().target) targ = xl_event().target;
 else if (xl_event().srcElement) targ = xl_event().srcElement;
 if (targ.nodeType == 3) // defeat Safari bug
  targ = targ.parentNode;
 return targ;

}

And here’s a function that uses our cross-browser event object if we are not in IE:

// By default, use window.event so we don't depend on attaching an event handler at the document level.
// Otherwise, use the cross-browser event object.
function xl_event()
{
  if (window.event) return window.event;
  else return ff_event;

}

Now we can write this:

	if xl_eventtarg.id = "link1";   // works in IE and FireFox.

I recommend you create a library of functions for this sort of cross-browser stuff. In this case, you can place:

  • xl_AttachEvent
  • xl_FFEventHandler
  • xl_event
  • xl_GetEvent
  • xl_eventTarg

in a library.

And, in order to use the global event variable, you’ll need this line of code (and one for each event type you want to trap) in the top of your script:

xl_AttachEvent(document, "click", xl_FFEventhandler);

As noted in several places of this post, I’ve relied heavily on PPK and his quirksmode.org site for help in understanding the various event models, etc. I’ve just ordered his book, and recommend anyone else who is serious about writing quality Javascript code do the same. Thanks, Peter.