Archive for the ‘Javascript’ Category

PyCon 2010 Poster Session

Saturday, February 27th, 2010

I finally presented something at a Python conference. Many thanks to Vern Ceder for organizing the PyCon 2010 poster session!

Here’s a copy of the poster, which describes a way to run QUnit-based JavaScript unit tests using Python’s unittest facilities:

PyCon Poster.png
PyCon Poster.pdf

The code described by the poster is available from bitbucket.org, under the BSD license.

Ted Leung on web app design patterns

Sunday, September 13th, 2009

DjangoCon 2009:

“Avi Bryant’s keynote took its root in his experiences building Trendly. As one might expect, Avi started building Trendly using Seaside. But by the time he finished, he noticed that very little of Seaside was actually being used. He attributed this to the fact that Trendly’s architecture involves loading a single HTML, with a ton of Javascript. That Javascript then manages all of the interaction with the server, which consists of snippets of JSON data. This range true to me because we used a similar architecture for Chandler Hub, the web based version of Chandler (our interaction with the server was based on atom and atompub, not JSON), and it’s the kind of architecture that GMail is based on.”

The same has been true for us (Mesa Analytics) in most of our web applications. Sometimes we do have “multi-page” web apps, but each of the individual pages typically follows the pattern above: load, then let JavaScript drive a bunch of task-specific server interactions.

Between Ted’s summary of DjangoCon 2009 and the chatter about Tornado, it has been an interesting week for web application developers.

ActionScript: TileList, deleting, scrolling backwards

Wednesday, August 19th, 2009

[Another day, another blog cross-post...]

I have a Flex app which shows users a TiledList of chemical structure depictions. Since it can be a large list, it’s lazy-loaded from the server as the user scrolls through the list.

Users can delete items from the list, with undo. In order to do this with reasonable performance, once the app has received confirmation from the server that an item has been deleted, it clears out the single deleted item from its local lazy-list.

To undo the deletion locally, the Flex app fills the correct lazy-list entry with an ItemPendingError; that error gets thrown as soon as the TileList tries to retrieve the item.

All of this works okay when the row containing the undeleted item is already visible. On the other hand, if the user has scrolled away from the row where the undeleted item will reappear, then when (s)he scrolls back the TileList simply empties out that item and all of the successive items in the row. Ugly!

ugly_repaint.png

Workaround

When the item is undeleted, immediately try to retrieve it via getItemAt(itemIndex). Catch the resulting ItemPendingError and register an ItemResponder. When the ItemResponder’s result or fault method is called, tell the TileList to invalidateList(). If the undeleted item actually contains a value, the TileList will repaint correctly — no more unsightly gaps.

import mx.collections.errors.ItemPendingError;
import mx.collections.ItemResponder;
[...]
try {
    structures.getItemAt(offset);
} catch (e:ItemPendingError) {
    e.addResponder(
    new ItemResponder(
        function(result:Object, token:Object = null):void {
            tilelist.invalidateList();
        },
        function(error:Object, token:Object = null):void {
            tilelist.invalidateList();
        }));
}

Firefox 3.1b2, Safari 4 Beta and HTML 5 canvas text

Wednesday, March 4th, 2009

This will be useful for depicting chemical structures using HTML5 canvas: both Safari 4 beta and Firefox 3.1b2 support the HTML5 canvas text rendering APIs.

There are still rough edges, e.g. it’s hard to measure text dimensions and therefore hard to position text properly. Still, it’s great to see!

$(document).ready(function() {
    function redraw() {
        var canv = $('#canv');
        var w = canv.width();
        var h = canv.height();
        // Let canvas know how big CSS wants it to be.
        canv.attr("width", w);
        canv.attr("height", h);
        var ctx = canv[0].getContext("2d");

        ctx.clearRect(0, 0, w, h);

        var msg = "Hello, Safari text.";
        var fontSpec = "24pt Verdana";

        // Find out the dimensions of the rendered msg.
        var e = $('<span style="visibility:hidden;font:' + fontSpec + '">' +
                  msg + '</span>');
        $('body').append(e);
        var tw = e.width();
        var th = e.height();
        e.remove();

        ctx.save();
        ctx.translate(w/2, h/2);
            // Indented to highlight transformation state.
            ctx.save();
            ctx.rotate(-45 * Math.PI / 180.0);
            ctx.translate(-tw/2, th/2);
            ctx.font = fontSpec;
            ctx.fillText(msg, 0, 0);
            ctx.restore();
        ctx.restore();
    };
    redraw();
});

Mozilla Webdev » Blog Archive » Native JSON in Firefox 3.1

Monday, February 16th, 2009

Mozilla Webdev » Blog Archive » Native JSON in Firefox 3.1:

“Pretty easy huh? And here’s how to get a JSON string from an object:

var personString = JSON.stringify(person);”

As a long-time fan of Python’s pickle and shelve, I hope JSON.stringify properly handles JavaScript object graphs. And I hope jQuery exposes a similar API.

I think jQuery provides only .param, which is designed as a helper for forms serialization and which does not handle nested objects. For example, in jQuery 1.3.1 this:

var graph = {
    'item': {
        'name': 'bob',
        value:42
    },
    'index': 1};
$('#msg').html("Graph: " + $.param(graph));

produces this:
Graph: item=%5Bobject+Object%5D&index=1

Release:jQuery 1.3 – jQuery JavaScript Library

Wednesday, January 14th, 2009

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

Monday, January 5th, 2009

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

Monday, December 8th, 2008
  • 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

Tuesday, November 18th, 2008

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">

Referencing external stylesheets in WordPress

Saturday, November 1st, 2008

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!")