IE6/7 CSS Specificity Bug

After our team launched the new College of Education site, I discovered that IE8’s handy “Browser Mode: IE7” mode of IE8 is useless for real IE7 testing (but IETester actually works!). Undoubtedly this “IE7 mode” has many quirks in its emulation we’ll never know about, but after a few hours of hair-pulling I finally pinned down a real IE6/7 bug that the emulator doesn’t have.

IE versions before 8 apparently vary in their calculation of CSS specificity depending on the order of elements in the selectors. What this means for poor suckers who worry about IE6/7 is that rules that appear later and (should) match specificity won’t always override values. E.g.

<div id="foo"><div id="bar">I should be green.</div></div>
/* both rules have the same specificity */
#foo div  { background:red   /* IE6/7 apply this value */ }
div  #bar { background:green /* correct value to apply */ }

This bug will hit you when you’re pursuing a good goal: trying to keep selectors short. So in these situations make sure to test in IETester at the very least and leave a comment to let future CSS editors know why a selector is longer than needs to be.

Filtering WordPress Navigation Menus

WordPress 3 introduced native navigation menus, usually created via the wp_nav_menu theme function and the built-in Custom Menu widget.  If you have a menu with a deep hierarchy, you may want to display only the active branch and the submenu directly below the active item (given class “current-menu-item” by WordPress). You can see this menu behavior on the left in the UF College of Education Faculty site.

This is sadly not doable with CSS. I originally did it with Javascript, but the requirements of progressive enhancement required that the whole menu be output before attacking the DOM. Depending on the page, this caused a distracting collapse of the menu during the layout.

The class Coewp_MenuFilter does this menu filtering server-side. Until I wrap this in a plugin, just put it in your theme folder:

// in functions.php
require dirname(__FILE__) . '/MenuFilter.php';
Coewp_MenuFilter::add();

How it works

add() attaches a filter to the “wp_nav_menu” hook, so WordPress passes menu HTML through the class’s filter() method before returning it in wp_nav_menu(). In filter(), the HTML is converted to a DOMDocument object, which is edited using DOM methods (with XPath available, this version was almost a direct port of the jQuery version). After cutting it down, the DOM tree is re-serialized to HTML.

I was really hoping this filtering could be done before the HTML was created, say by subclassing WP’s Walker_Nav_Menu class, but this proved difficult to debug.

Simpler API for Zend’s built-in Firebug Logger

Zend Framework has functionality to send messages to the Firebug console (via Firefox’s FirePHP addon), but if you’re not using the ZF front controller, the API is a bit of a pain. Besides your instance of Zend_Log, you must keep track of a few additional objects just to manually flush the headers after all your logging calls. Since I knew the old FirePHP class didn’t need this follow-up step, I figured I could just flush the headers after each send.

The result is FireLog. On the FireLog instance, calls to methods like log(), info(), warn(), etc. are proxied to an internal Zend_Log instance, while the methods send(), group(), and groupEnd() are proxied to the static methods on Zend_Wildfire_Plugin_FirePhp. In both cases the headers are set immediately using some simple ZF subclassing. Continue reading  

Gainesville: PHP/Javascript Developer Position Open

The Office of Distance Learning is seeking a web programmer with considerable experience with PHP, Javascript, and SQL to aid in the creation of and maintenance of several web and mobile applications.

The person we’re seeking will need a strong understanding of and experience with:

  • PHP5
  • Javascript
  • object-oriented and functional programming styles
  • related technologies such as SQL, CSS, the HTML DOM, Apache, and HTTP

Preferred applicants will be able to demonstrate:

  • sites/projects worked on, including open source projects
  • code created that is highly extensible, loosely coupled, testable, etc.
  • ability to create APIs/frameworks to be used by others
  • intuition of impact of code on underlying systems and client-side experience
  • ability to communicate well with teammates and end users

The applicant must be comfortable:

  • coding with third party libraries like Zend, jQuery, YUI, etc.
  • customizing third party applications like WordPress
  • using source control and documenting code

The Office of Distance Learning is an exciting, creative environment where we manage and customize applications like WordPress, Moodle, and Elgg, and serve thousands of users.

Search jobs.ufl.edu for Requisition number: 0806823

Closure Compiler is smarter than you

I’ve known about Google’s Javascript minifier, Closure Compiler, for awhile, but after sending a couple snippets through it today I realized it’s a pretty impressive piece of work.

Input:

function howManyMatch(arr, pattern) {
   var l = arr.length;
   var total = 0;
   var i = 0;
   for (; i < l; i++) {
       if (pattern.test(arr[i])) {
           total++;
       }
   }
   return total;
}

Output:

function howManyMatch(b,d){for(var e=b.length,c=0,a=0;a<e;a++)d.test(b[a])&&c++;return c};

Or with whitespace re-added:

function howManyMatch(b, d) {
    for (var e = b.length, c = 0, a = 0; a < e; a++)
        d.test(b[a]) && c++;
    return c
}

Optimizations:

  • shortened parameter names and removed unneeded semicolons (YUI Compressor already did this much)
  • combined multiple var statements into one declaration
  • moved that declaration into the first section of the for loop (to save one semicolon!)
  • removed brackets around blocks with only one statement
  • replaced if statement with && operator (to save two bytes)

Several of these are often done by JS devs by hand. With closure compiler on tap, we no longer have to. Just concentrate on readability and maintainability and let CC worry about size optimization.

?YouWontSeeMe

In beta 11, Opera’s going to hide all “http(s)://”, and also all querystrings (until you focus the addressbar). Opera’s devs are right that users consider them mostly “gibberish”, but I think this change could cause a ton of problems and confusion for people, especially support staff, and there are plenty of sites/apps still out there with URLs based on querystrings. I can see this setting as short-lived.

We need a frontend design tool for live web pages

It’s quite frequently that an HTML/CSS designer might want to make changes to a live web page. Maybe she doesn’t have write access, or maybe the fixes needed aren’t worth the start-up cost of copying the page locally and working on it there, or multiple designers want to work up ideas on a given page simultaneously. The “Inspect Element” capabilities of most modern browsers will let you make HTML/CSS changes to a live page, but navigating or refreshing causes those changes to be lost, and they’re hard to keep track of.

Here’s a feature wishlist:

  1. keep track of “Inspect Element” user changes with the ability to save them locally
  2. keep changes in discrete “changesets” that can be re-applied, or saved as a unified patch of the original files, or at least as the modified original files
  3. allow swapping page CSS files with user-controlled CSS files (e.g. file:/// or htttp://localhost/)
  4. allow swapped CSS files to be periodically “refreshed” so the user wouldn’t have to switch between CSS editor and browser.

Firefox’s Stylish extension looks to come close to (3), allowing you to add user styles to a page/site, like Greasemonkey does for Javascript. It doesn’t look like the editing experience is great, though.

You can manually do (3) and use the CSS Reload Every bookmarklet, but it reloads all CSS, which is kinda of jarring.

A bookmarklet could implement (3) and (4) and persist its settings in a cookie.

Other ideas?

Update: Here’s a bookmarklet that let’s you swap CSS files and stores its settings in a cookie for the current page. Next step is for it to allow adding files and controlling the cookie path.

You must enable Javascript! (right-click, add to favorites or bookmarks)

(CSSswap source).

Email Address Munging Still Mitigates Harvesting

At least a decade into the use of simple email munging on web pages (my own solution here) there’s a growing consensus—and it seems like common sense with the advancement of the web in general—that this surely can’t still work on modern harvesters. While trying to look up some old research I’d read about this, I came across this January 2010 post by a Project Honey Pot admin:

We’ve run tests on different munging techniques and find that they are still surprisingly effective. We have a page that has a set of differently munged addresses. The ones protected by Javascript have yet to receive a single message. Even simple things like using ASCII character encoding to hide the @ sign, or adding spaces to the addresses, is surprisingly effective at stopping harvesting.

Whether to munge or not is kind of a religious war, but I see this as pretty convincing evidence that munging isn’t obsolete just yet. Of course this or any other single prevention strategy isn’t a “solution”, but mitigation of the inevitable is still arguably worthwhile, especially for people without the luxury of having top notch admins run their mail server.

Using jQuery Before It’s Loaded

It’s better to include scripts like jQuery at the end of the BODY, but this makes its methods inaccessible earlier in the page (e.g. inside a WordPress post). What you can do is use a script like the one below to queue DOMReady functions before jQuery loads.

(function (w) {
    if (w.$) // jQuery already loaded, we don't need this script
        return;
    var _funcs = [];
    w.$ = function (f) { // add functions to a queue
        _funcs.push(f);
    };
    w.defer$ = function () { // move the queue to jQuery's DOMReady
        while (f = _funcs.shift())
            $(f);
    };
})(window);

Minified:

Setup

  1. Link to the script in the HEAD or at least before your typical page content area
  2. Link to jQuery at the end of BODY
  3. Below jQuery, include: <script>defer$()</script>

Now in the BODY you can use $(function(){ ... }); to queue up a function as if jQuery were already loaded. And, thanks to the fact that Javascript identifiers are referenced at run-time, you can call any other jQuery functions inside your queued function.

With some modifications you can use this pattern for any library with a similar DOMReady implementation.