Release:jQuery 1.3 - jQuery JavaScript Library

Release:jQuery 1.3 - jQuery JavaScript Library:
"Live Events

jQuery now supports 'live events' - events that can be bound to all current - and future - elements. Using event delegation, and a seamless jQuery-style API, the result is both easy to use and very fast."

If I read this correctly, now you can reload parts of your page and have any replaced controls wired up automatically. No more need for post-processing callbacks on $.load() or $.getJSON()?

Outstanding!

VoodooPad Bookmarklets

VoodooPad bookmarklets make it easy to log search results. I keep a worklog in VoodooPad. Notes for each day are stored in a page with a name of the form 'yyyy-mm-dd'. When I'm searching for info on the web, I like to include relevant results in my worklog. I tend to record results in this format, to make it easier to find the results again in future:

http://url.of.interest/:
"""
Excerpt
"""

It's tedious to format these excerpts. At least two visits to the browser application are needed:

  1. Copy the URL
  2. Copy the text of interest

Luckily VoodooPad supports application-specific URLs, and you can create JavaScript bookmarklets to open such a URL, with the URL and any selected text for the page you're currently viewing.

Here's an almost human-readable example of a bookmarklet which adds an excerpt from the current web page, formatted as above, to the current worklog page in VoodooPad. (Sorry for the messed-up syntax listing. Apparently Wordpress -- or maybe MarsEdit -- is trying to insert smart quotes.)

javascript:
var d = new Date();
var padded = function(v) {
    var res = v.toString();
    while (res.length < 2) {
        res = '0' + res;
    }
    return res;
};
var page = [
    String(d.getFullYear()), 
    padded(d.getMonth() + 1),
    padded(d.getDate())
].join("-");
location.href = ('voodoopad:description=' + 
                 encodeURIComponent(location.href + '\n"""\n' + 
                                    window.getSelection().toString() + 
                                    '\n"""\n') +
                 '&page=' + page);

Here's the same bookmarklet formatted for inclusion in your browser's menubar:

javascript:var%20d=new%20Date();var%20padded=function(v)%20{%20var%20res%20=%20v.toString();while%20(res.length%20<%202)%20{res%20=%20'0'%20+%20res;}%20return%20res;};var%20page%20=%20[String(d.getFullYear()),%20padded(d.getMonth()%20+%201),%20padded(d.getDate())].join('-');location.href='voodoopad:description='+encodeURIComponent(location.href+'\n"""\n'+window.getSelection().toString()+'\n"""\n')+'&page='+page;

Things I like about ActionScript 3

  • Concise, path-based data binding
  • Packages
  • Importable modules
  • Classes, with inheritance

After several years of working with JavaScript < 1.7, these features make ActionScript really attractive.

I've also hit several snags. Maybe I'll write those up separately...

Can't debug after updating to Flex Builder 3.0.2

I'm evaluating FlexBuilder 3, and have just installed the Flex Builder 3.0.2 update. All of a sudden I can't debug my AIR project.

The error dialog displays a lengthy message which ends with:

error while loading initial content 

Thanks to Google and Adobe's public bug database, the fix is straightforward: edit the project's *-app.xml file and change the namespace (2nd line) to 1.5:

<application xmlns="http://ns.adobe.com/air/application/1.5">

One-line web server in Python

From Ed Taekema's weblog, a reminder[1] about how to create a web server in one line of Python:

python -c 'import SimpleHTTPServer;SimpleHTTPServer.test()'

This starts a server listening on port 8000, serving files from its launch directory. If you just hit the server (http://localhost:8000/) it will by default serve index.html; if index.html doesn't exist, it will give you a directory listing. Also, the server will provide only those files residing in or below the current working directory; e.g. http://localhost:8000/../ resolves to the default document.

Wish I'd seen Ed's note this morning...

This is handy when you want to experiment with things like interactions between Flex applications and JavaScript, or other situations in which you can't get by with simple file:/// URLs. This would be handy as a jqUnit test, as well.


[1] Reminder? It's been a long time since I read "Internet Programming with Python" :-)

Referencing external stylesheets in Wordpress

How to Protect CSS Mods for ANY WordPress Theme

Almost exactly what I was looking for -- thank you!

Unfortunately, I still don't know how to prevent WordPress from stripping class tags from my <pre> links, when I post from MarsEdit.

Update

The MarsEdit forums provide a solution:

the "class" attribute is not allowed by default with the "kses.php" file in WordPress. I guess after editing that file and allowing class as an allowed attribute, it is working fine.

Indeed, it is:

#!/usr/bin/env python3.0

for i in range(10): print("Mon Dieux, it works!")

Removing old man pages from OS X Leopard

Back in January I posted about Leopard, 'ls -l' and extended attributes. The gist was that my man pages were out of date, so they didn't explain what the @ character represented, in 'ls -l' output.

Some threads on the Apple discussion boards have investigated why the man pages don't get updated. The conclusion is that Leopard installs a lot of gzip-compressed man pages without deleting the corresponding uncompressed man pages. (It may be that this is true only for upgrade installs.) A recommended workaround was to scan through the man page directories with a shell command, re-locating all uncompressed man pages which had corresponding compressed man pages.

I decided to be cowardly in doing this. Here's a Python script which moves each uncompressed man page only if it is older than its corresponding gzipped man page.

The script must be run with superuser privileges, e.g.

$ sudo python mv_old_man_pages.py

It processes all of the man pages under /usr/share/man, moving old, uncompressed man page files to ~/tmp/old_man_pages.

I would post this to the Apple discussion forums, but it's really overkill. The short shell scripts already posted should work fine, if you ignore the harmless error messages and process each man/man* directory manually.

#!/usr/bin/env python
# encoding: utf-8
"Remove obsolete uncompressed man pages on an OS X Leopard system."

import sys, os, logging

def candidateOldManPages():
    os.chdir("/usr/share/man")
    for dirpath, dirnames, filenames in os.walk("."):
        for f in filenames:
            if f.endswith(".gz"):
                fOld = f[:-3]
                if fOld in filenames:
                    yield os.path.join(dirpath, f), os.path.join(dirpath, fOld)

def findOldManPages():
    for p, pOld in candidateOldManPages():
        s = os.stat(p)
        try:
            sOld = os.stat(pOld)
        except os.error, info:
            # Some man pages may be broken symbolic links
            logging.warn("Can't stat (%s, %s): %s" % (p, pOld, info))
            if os.path.islink(pOld):
                yield pOld
        else:
            if s.st_mtime > sOld.st_mtime:
                yield pOld

def mvOldManPages():
    topDestDir = os.path.expanduser("~/tmp/old_man_pages")
    for relpath in findOldManPages():
        dirname = os.path.dirname(relpath)
        filename = os.path.basename(relpath)

        destDir = os.path.join(topDestDir, dirname)
        if not os.path.exists(destDir):
            os.makedirs(destDir)

        logging.debug("mv %s %s" % (relpath, os.path.join(destDir, filename)))
        os.rename(relpath, os.path.join(destDir, filename))


def main():
    logging.basicConfig(level=logging.DEBUG,
                        format="%(levelname)s: %(message)s")
    mvOldManPages()

if __name__ == "__main__":
    main()

CMake

Last spring I evaluated waf as an alternative to SCons (and its 3rd party Qt4.py plugin) for Qt4 projects. I've finally settled on CMake.

waf's wscript files could be beautifully concise. Alas, support for Qt4 applications was unstable, and the support for building OS X application bundles was both rudimentary and unstable. (By "unstable" I mean that the qt4 and osx tools would break periodically, and/or that the internal APIs would change so much between releases that my own customizations would break.)

The final straw was that I could not control the library order when linking static Qt4 libraries. That made it impossible for me to build Qt4 apps which used QtSvg.

I wish I had time to document these problems properly -- no doubt waf's maintainer(s) would prefer bug reports to detail-free claims that "it doesn't work."

In any case, CMake seems to be doing the job. It can perform out-of-line builds, supports defining and running unit tests, and doesn't get in the way of writing integration tests in Python, to drive e.g. C++ programs. It knows how to build Qt4 applications and lets me control the link order for static libraries. And it works well on OS X and Linux.

Compiling subversion 1.5.1 on OS X 10.5.4

I've just tried to compile the subversion 1.5.1 client from its two source tarballs (subversion-1.5.1-tar.bz2 and subversion-deps-1.5.1-tar.bz2). I took care to first hide the /usr/local libraries from my existing subversion installation. Even so, the compilation failed, complaining

/usr/lib/libexpat.a: No such file or directory

The workaround was to temporarily move the system's /usr/lib/libexpat* dynamic libraries, and then to rebuild.

Here's the build script which worked for me:

#!/bin/sh
set -e
VERSION=1.5.1
rm -rf subversion-${VERSION}
tar xjf subversion-${VERSION}.tar.bz2
tar xjf subversion-deps-${VERSION}.tar.bz2
cd subversion-${VERSION}
./autogen.sh
./configure --without-apxs --with-ssl 
make
sudo make install
sudo make install-swig-py

New TextMate bundles

These aren't really new. I just wasn't aware of them.

JavaScript Tools

The JavaScript Tools bundle helps you lint, format and compress your JavaScript code, and convert code to and from JavaScript bookmarklets.

My favorite feature: whenever you save a JavaScript file via Command-S, the bundle automatically runs it through jslint. If any errors or warnings are found, a tooltip appears which shows the number of warnings/errors.

If you run a full validation using Control-Shift-V, you'll get a popup window showing "compilation" results -- complete with syntax errors and clickable links to take you to the offending source code.

Installation

I installed under ~/Library/Application Support/. It may be better to use /Library/Application Support/.

$ cd ~/Library/Application Support/TextMate/Bundles
$ svn export http://bundles.bundleforge.com/trunk/bundles/JavaScript%20Tools.tmbundle/

BTW I'm not sure why export is preferred over checkout.

If TextMate is already running, you can load the bundle by selecting Bundles->Bundle Editor->Reload Bundles.

Sproutcore

I haven't done much with Sproutcore yet, but it does already have its own TextMate bundle which provides a few tab-completion snippets.

Installation
$ cd ~/Library/Application Support/TextMate/Bundles
$ curl --location --get http://github.com/sproutit/sproutcore-tmbundle/tarball/master -o sproutcore-tmbundle.tar
$ tar xf sproutcore-tmbundle.tar

The curl --location option is required, since github will issue a redirect.

The extracted tarfile will have a root directory name of the form sproutit-sproutcore-tmbundle-.*, so a directory rename is needed.

$ mv sproutit-sproutcore-tmbundle-blah-blah.../ Sproutcore.tmbundle