So, this afternoon, I spent about four hours and played around with Raphael, the SVG library for HTML 5, and the native Canvas renderer.  Originally, I was only going to go with Raphael, until someone pointed out to me that Raphael doesn’t work on Android phones.    Since my apps have to work on Android phones, I had to find a Canvas alternative.

And I do believe it qualifies as an “alternative.”  Although in both Firefox and Opera, the Canvas and SVG apps look the same, in Chrome (I’m running 12.0.733.0) the Canvas version has noticeable flicker, poor management of the DIV/Canvas size relationship (even when using jQuery, and even after onReady!), and doesn’t quite look the same.

Raphael arcs are… difficult.  They’re elliptical arcs and the SVG language describes a path between two points, with two radii of the ellipse (a horizontal and a vertical), two flags indicating whether or not the arc’s sweep is positive or negative and to go the long way or the short way, and rotation transformation of the final arc.  It took me a long time to wrap my head around the meaning of all the different possibilities.  Canvas arcs are purely circular so they’re more easy to define, but their endpoints are less distinct so creating a “fill” between two line-arcs required more math.   Either way, the learning curve on drawing roundy things is rather steep.

You can see the results in my Raphael and Canvas Experiment project.  The most interesting experiment is Both Arcs, which shows the two arcs being written side by side, Canvas on the left, SVG/Raphael on the right.  If you’re running Chrome, you might see the gradient flicker annoyingly.  Still, this was a lovely opportunity to play with Canvas, Raphael, and animation.  The source code to the final experiment is written in HAML and Coffee, because that’s just how I roll.  A Makefile is provided.  There wasn’t enough CSS to justify using LessCSS.

17Jun

Satchmo… arrrgh

Posted by Elf Sternberg as django

Here’s what annoys me most about Satchmo: it wasn’t written by Django developers.  Or, at the very least, it wasn’t written by Django developers who had ever bothered to read Jacobian’s Django in the Real World.

I was trying today to customize the view of the Satchmo store as provided by the clonesatchmo.py program.  I discovered, to my frustration, that while most of the store is (rightly) kept under the /templates/store path, the “buy a product” page is kept under /templates/product. Why? This is a little bit like saying that the shelf on which a product is stored is part of the product!

It’s also the case that satchmo.store depends on satchmo.payment — and satchmo.payment depends on satchmo.store!  Is it too much to ask that these dependencies be factored out into a common base upon which both libraries depend, rather than creating this circular (and untenable) dependency graph?

Satchmo calls itself “the webstore for perfectionists with deadlines,” but it’s bondage to its own architecture is a tragic exercise in frustraction.

I love LessCSS, because it allows me to write CSS as code, with consistent thinking throughout. Today, I’m going to show you how to have button-shaped anchors with consistent gradients throughout your page, using the color scheme you’ve initially chosen.

LessCSS allows you to have parameterized mixins, small blocks of CSS that you can easily incorporate into other blocks of CSS. Let’s say I wanted to create two styles, “orange” and “blue,” based on two colors from my palette. Some buttons will be used for inner functions, some for outer commands. For my program, I want them to be anchors; they’re just taking you to views, not committing data. I have a consistent color for my border and text color; it’s only the background I’m showing how to highlight here.

.background_gradient(@base) {
    color: #fef4e9;
    border: solid 1px #da7c0c;
    background: @base;
    background: -webkit-gradient(linear, left top, left bottom, from(lighten(@base, 5%)), to(darken(@base, 5%)));
    background: -moz-linear-gradient(top,  lighten(@base, 5%), darken(@base, 5%));
}

See those ‘lighten’ and ‘darken’ commands? They’re a part of LessCSS; they automatically do exactly what they purport to do: lighten or darken the base color passed in. To see how these are used:

@orange_base: #f78d1d;
.orange { .background_gradient(@orange_base); }
.orange:hover { .background_gradient(darken(@orange_base, 10%)); }
.orange:active { .background_gradient(lighten(@orange_base, 10%)); }

@blue_base: #7db8db;
.blue { .background_gradient(@blue_base); }
.blue:hover { .background_gradient(darken(@blue_base, 10%)); }
.blue:active { .background_gradient(lighten(@oblue_base, 10%)); }

Now my CSS document will have two classes, “orange” and “blue”, which will resemble one another in the consistency of their gradients, saturation and value changes as they transition between the no-focus, hover, and active states. Pretty sweet consistency, and once you have a snippet like background_gradient, you can use it everywhere.  LessCSS provides functions for other color operations, such as ‘saturate’, ‘desaturate’, ‘spin’ (which rotates the color along the color wheel), ‘fadein’ and ‘fadeout’ (which affect the alpha channel of the color, if your browser supports those).  Now that’s super-cool.

LessCSS has been re-written in Javascript, meaning that you can now write your “style.less” and not have to pre-process it; the page will automatically parse it for you and re-feed it to the browser as CSS.  All you do is include lesscss.js in your page.  I still do pre-processing for the same reason I do minification and collapsing: performance.  But it’s nice to have this option.

If you’re one of those early adopters of LessCss, then you probably know by now that development of the original Ruby version has been abandoned in favor of a version that runs under Node.js. I’m a big fan of LessCss; both the nested definitions and parametric definitions make my life a whole lot easier.

I installed the latest version today and noticed that it’s missing a feature I really liked in the Ruby edition: the “watch” feature. This would allow you to edit your LessCss source document, and would automagically re-run the compiler to produce valid CSS. You wouldn’t have to run it by hand to tweak your document. The Node.js version of LessCss doesn’t have this feature.

It’s possible to get the same effect, however, if you’re running a system that uses inotify. If you have inotify in your kernel, install inotify tools, and you’ll have the program inotifywait, which is a useful tool for the command line that waits until a file changes, and then allows your script to proceed.

In bash, the code is:

while true; do inotifywait style.less ; lessc style.less style.css ; done

That’s it. Now, every time you save your LessCss file, the css equivalent will be automatically generated.

You’re a geek in need of a job. In the meantime, you need to convince unemployment insurance that you’re looking for a job. For the latter, you need to send out a few resumes every week, and go to any interviews that arise as a result of your efforts.

For both of these, RSS is your friend. Get yourself an account on Google Reader, or install a copy of Liferea, and then put the following into a folder entitled “Job search:”

NPost
http://feeds2.feedburner.com/nPostJobPostings
Startuply Seattle
http://www.startuply.com/Rss/Search.aspx?s=in%2098148
Craigslist Web jobs
http://seattle.craigslist.org/web/index.rss
Craigslist Computer Engineering jobs
http://seattle.craigslist.org/eng/index.rss
Craigslist Software, QA, and DBA jobs
http://seattle.craigslist.org/sof/

That’s basically it. That’s your twice-a-day scan (breakfast and lunch) of job postings. If you’re in a different region, obviously use a different Craigslist origin and change the zip code on Startuply.

Also, if you use Firefox, take all the other jobs listings and put them in a single bookmark folder (use the bookmark organizer under “Bookmarks” to find it), and when you check your listings in your reader, go to that folder, right-click the folder, and choose “Open All in Tabs.” That’ll then give you a reliable, repeatable, scannable experience twice a day. After a few days, you’ll get into the rhythm of your job search page collection and be able to separate the viable posting from the ridiculous ones in a matter of minutes.

Firefox supports the displaying of RSS. You might just want to use it instead of Google Reader. Also, Monster.com will give you a customized RSS feed if you use Firefox, because Firefox supports persistent authentication.

Here are the job boards I get using the Firefox trick:

Write four or five cover letters with sections bolded where you will customize the letter for the given position. There shouldn’t be any bold when you actually post it. Make it clear that the letter you’re sending them isn’t exactly a form letter, but was written with the job posting you’re responding to explicitly in mind. (Cut and paste is your friend here.) Do the same with resumes, especially if you have several job skills. As both a Django and Javascript developer, I have two resumes, one that leads with my Django and Pylons experience, the other that leads with my Javascript, jQuery, and Ext experience. (Actually, I have more than that, but this is a solid example.)

Have copies of your resume in pure HTML. This will be useful when you’re faced with one of those “paste your resume into our textbox here for keyword scanning” robots so endemic to midsize companies that don’t have the time to actually think about you as a candidate.

p.s. I don’t actually need a job at this moment.  I’m working for an amazing start-up.  But a friend of mine asked me how I found work, and this was part of my toolkit.  I’ve had recruiters beg me for this explanation.  But it’s so obviously easy, I don’t understand why other people haven’t done it.

Ever have the problem where you want to fade out a whole collection of stuff, and then show only one? A naive implementation looks like this:

$('.options .option').fadeOut('fast', function() {
    $('.options .option:eq(4)').fadeIn('fast')});

If you have five options, however, the callback gets called five times. Now, this is okay in the current example: fadeIn is idempotent, meaning that it doesn’t do any harm to call it multiple times as the target object is already faded in after the first; the rest result in no-ops. But what if you need to ensure that the callback gets called only once? What if you have multiple distinct animations that you need to ensure are complete before triggering the next set? Use an aggregated promise. To the best of my knowledge, jQuery.animate() still returns the jQuery root object and not a promise, but we can work around that, like so:

var promises = $('.options .option').map(function() {
    var dfd = $.Deferred();
    $(this).fadeOut('fast', dfd.resolve);
    return dfd.promise();
}).get();

$.when.apply(null, promises).then(function() {
    $(".options .option:eq(" + target + ")").fadeIn('fast');
});

Here, we return an array of promises, the resolution of each of which will be called when the fade out of each particular DOM object is done. when() all the promises are delivered, then the fadeIn is triggered. The call to get() at the end of the map() ensures that when() gets an array of promises, not an array of jQuery objects wrapping promises, which wouldn’t make sense.

This technique can be used to synchronize any multiple animations and ensure that all of them finish before proceeding to a new animation.

The title is tongue-in-cheek, but take it in good faith: your most ardent users, the ones who link to you and provide you with both traffic and search engine legitimacy, can also be your biggest nightmares. Because when they link to you, they won’t just link to your home page. They’ll link to what they love deep within your site, and six months later, when you re-arrange, those links will go to odd places and crash zones, and GoogleBot and BingBot will follow those links and fill your error logs.

Dealing with those is a chore, but here’s what I’ve recently discovered: filter them out. Filter out all hits from GoogleBot and BingBot from your error logs and you’ll be left with a gem: the errors caused by human beings actually using your site. Target those first, then work on closing the nuisances caused by automated probes.

03Feb

Backbone Store v 0.2 released

Posted by Elf Sternberg as javascript, programming

The last version of the Backbone Store was pretty sloppy. I’ve cleaned it up, with some serious revisions to both the code and the commentary, and you’re welcome to look it over. As always, it’s available from my Github.

In case you’ve been under a rock, the jQuery team released version 1.5 this afternoon, and in a move that took me completely by surprise, jQuery 1.5 includes Futures and Promises. Well, that’s fine, but what the Heck are futures and promises?

A Promise is a proxy for a result that hasn’t arrived yet. In event-driven programming, such as browser-side development, this is huge. If you have several events that might happen in a non-determinate order, the callback might be a functor with a counter for the number of events to be aggregate into a “all done” event. With jQuery’s Deferred pattern, that gets reversed to

 $when( getSchemas(), getData() ).then(function({  app = new MyApplication(); }); 

How cool is that? Practical demos to follow as soon as I get my head around the whole API.

20Jan

Using django_uni_form and CSRF

Posted by Elf Sternberg as django, programming

The last update I have to django_uni_form, a rather amazing form layout handler for Django, does not understand what to do with the CSRF token. So in case you’re wondering, after you’ve created your form, you do the following in your view:

        form = FilmForm(initial = {'title': 'History is ...'})
        form.helper.add_input(Hidden(name = 'csrfmiddlewaretoken',
                                     value = request.META['CSRF_COOKIE']))

It’s unfortunate that you have to do it in the view, but it’s the only way to have access to the request.META object, which is where the current CSRF token is stored.

Recent Comments