Blake (old posts, page 17)

X-Tag: or how to cut your html in half by adding 28 lines of Javascript…

As a side-project, I’ve been working on a prototype which is heavily based on a demo page from Stephen Horlander. Now, that page is pretty amazing, but if you look at the source (using command-u or control-u in Firefox, and command-alt-u or control-alt-u in Chrome), you’ll see a lot of code that looks like this:

<div class="menuPanelButton subscribeButton">
  <div class="button"></div>
  <div class="label">Subscribe</div>
</div>

and:

<div class="customizeToolbarItem">
  <div class="customizeToolbarItemIcon share"></div>
  <div class="customizeToolbarItemLabel">Share</div>
</div>

Now, one or two of those would be fine, but when we get into more than that, the repetition really starts to bug me, and I think “Wouldn’t it be better if I could just write stuff like:

<panel-button type="subscribe">Subscribe</panel-button><toolbar-item type="share">Share</toolbar-item>

instead?” And it turns out I can, using a new library called x-tag! The first thing I need to do is register the new tags I’ll be using. That’s done with code like this:

// These first two lines are here because I’m using require.js, which I’ll
// talk about in a future blog post…
define(function (require) {
  require(["jquery", "x-tag"], function($, xtag) {

    // And this is the meat of the functionality.
    // First, we’ll register the new "panel-button" tag.
    xtag.register("panel-button", {
      onCreate: function(){
        var self = $(this);
        // When the tag is first seen, make the innerHTML be this stuff below.
        self.html("<div class='menuPanelButton " + self.attr("type") + "'>" +
                    "<img src='images/button-" + self.attr("type") + ".png'" +
                    "     class='button'>" +
                    "<div class='label'>" + self.text() + "</div>" + 
                  "</div>");
      },
    });

    // And then, we’ll register the new "toolbar-item" tag.
    xtag.register("toolbar-item", {
      onCreate: function(){
        var self = $(this);
        // We could also replace this element with the html below, but I
        // haven’t done that here because I haven’t needed to yet.
        self.html("<div class='customizeToolbarItem'>" +
                    "<div class='customizeToolbarItemIcon " + (self.attr("type") || "") + "'></div>" +
                    "<div class='customizeToolbarItemLabel'>" + self.text() + "</div>" +
                  "</div>");
      },
    });

  });
});

The second step is to replace all the old html with the new tags. (I did that, too, of course.) And there we go. That’s it. In the file I was modifying, the combination of that and moving the javascript out into a separate file took the html from 275 lines down to 146 lines, and let me more easily change the buttons around, and add new ones. I call that a win, and from now on, whenever I see large blocks of repeated html, I’m going to be seriously tempted to switch them to an x-tag!

One caveat I will mention is that in my first attempt, I tried to use both the content property, and the onCreate method, and that totally didn’t work, since the content would be replaced by the value of the content property long before I had a chance to muck around with it in the onCreate. So in the future, I think I’ll just jump straight into using the onCreate method, since it’s not that much harder.

Requiring jQuery UI.

Yesterday afternoon, I watched a video from James Long about Mortar, which is a template for making HTML 5 Open Web Apps. Now, coincidentally, I’m starting a new project (in my spare time, obviously, since it’s a Sunday), and while it’s not an Open Web App, I saw no reason not to use the same tools they were using.

Of course, since nothing’s easy, I ran into a problem pretty quickly. My problem was that every time I tried to require("jquery-ui");, I got an error of “ReferenceError: jQuery is not defined”. There wasn’t a lot of information about how to fix it, so after most of an afternoon mucking around, I finally came up with something that seems to work, and thought I would post it.

  1. Go into your www/js/lib directory.
  2. curl -O https://ajax.googleapis.com/ajax/libs/jqueryui/1.8.18/jquery-ui.js
  3. Edit the jquery-ui.js file. At the top add the line define(["jquery"], function (jQuery) {, and at the bottom, add the line });.
  4. That’s it. From there you should be good to go!

Now, I suspect there’s a better way to do this, and hopefully James or Bryan will jump in the comments and tell me what it is, but for now, at least this works.

Adventures in Mail Servers (or, how I wasted my Sunday afternoon)

I think what I want is pretty simple, or at least, reasonably common. I’m just looking for a couple of programs.

An SMTP server which will accept mail for the accounts at latte.ca, and deliver it to a Maildir of my choosing, and let me send mail through it if, and only if, I’ve logged in with the password to that account. (Being able to define a few aliases would also be nice.)

And an IMAP server which will expose the previously-mentioned Maildir, after I’ve logged in with the password to that account.

And yet, every time I try to set that up, something completely falls over for no particularly understandable reason, and I end up wasting an afternoon (or more) of my life. I had hoped this time would be different, since I decided not to install and configure everything myself, but instead bought a copy of OS X Lion Server which was supposed to do all the hard work for me. I’m not going to enumerate all the problems I ran into, but I will say that I still haven’t managed to get there. I’m just done for tonight.

Anyways, if anyone reading this has a working setup that meets the requirements (and the added requirement of needing to use Dovecot and Postfix, since those are what’s installed), I would love to get a copy of their config files. And in the meantime, I might seriously look into getting a refund for Lion Server, given how badly it’s failed me. :P

Building Thunderbird on OS X Lion (10.7) and XCode 4.2

A few people recently asked me about building Thunderbird on the latest version of Mac OS X. Since I have it working, and to give myself a place to point to the next time they ask, I figured it would be a good idea to blog about it.

So, here’s my .mozconfig.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
# Debug .mozconfig
mk_add_options MOZ_MAKE_FLAGS=-j4
mk_add_options MOZ_OBJDIR=@TOPSRCDIR@/../objdir-`basename \`pwd\``-`hg branch`
# mk_add_options AUTOCONF=autoconf213
ac_add_options --enable-application=mail
ac_add_options --enable-extensions=default,inspector
ac_add_options --enable-inspector-apis

# Compilation options
ac_add_options --disable-optimize
ac_add_options --enable-debug
ac_add_options --enable-tests
ac_add_options --disable-jemalloc
#ac_add_options --enable-trace-malloc
ac_add_options --enable-chrome-format=symlink

ac_add_options --with-macos-sdk=/Developer/SDKs/MacOSX10.7.sdk
ac_add_options --enable-macos-target=10.7

# For NSS symbols
export MOZ_DEBUG_SYMBOLS=1
#ac_add_options --enable-debug-symbols="-gdwarf-2"

#Use ccache
#ac_add_options --with-ccache=/usr/local/bin/ccache

# We don't have GCC anymore, since XCode 4.2, so use clang instead.
CC=clang
CXX=clang++

There are probably a bunch of things I don’t really need in there, so if anyone wants to take it, and cut it down to the minimal set, I would definitely appreciate it. But in the meantime, this works for me, and will probably work for you, too.

What angle would you cut a circle at to divide it into thirds?

The other day I was reading a tweet from Neil deGrasse Tyson, and it got me thinking… If you were going to cut a circle into three equal pieces using only two cuts, what would the angle to cut them be? (Θ in the diagram over on the right side there.) So I asked on Twitter, and eventually got a reply. This is my attempt to reconstruct the reasoning behind the answer.

The easiest way to figure this out, I believe, is to cut the circle in half, and then figure out what line divides the semicircle into a 2/3rds to 1/3rd ratio. So let’s do that, and label the points A, B, C, and O (for the origin), as shown on the left. We’ll also label the angle AOB as ɣ, because we'll be using it a little more later.

We know from this page that the area of a segment is r² × (ɣ - sin ɣ) / 2, and we want the segment formed by the line AB to contain 1/3rd of the total circle (or 1/3 × π × r²). Putting those together gives us the equation:
r² × (ɣ - sin ɣ) / 2 = π × r² / 3
multiplying both sides by 2, and diving both sides by r², we get
(ɣ - sin ɣ) = 2 × π / 3
Now all we have to do is simply solve for ɣ to get:
ɣ = 2.60533

That means that the angle BOC is π - ɣ, or 0.53626 radians (or 30.7º). Now, the inscribed angle is half the central angle, so in theory, to get the angle BAD, I should divide that by two, but then I’ll just need to multiply it by two again to account for the other half of the circle, so let’s skip all that, and just call it 30.7º.

What the heck am I pushing, anyways?

Much of the new work I’m doing these days is being stored in git repositories. Now, I’m not the biggest fan of git, particularly its UI, but the advantages of GitHub and GitX are hard to ignore. Despite that, I still really missed being able to type hg out to see which patches I would be pushing, so, after a short chat with (and demo from) Ben, I came up with the following:

Somewhere in your path, add a file named git-outgoing which contains the following contents:

# !/bin/sh
# Uh, there shouldn’t be a space between the # and ! in the previous
# line, but the highlighter I’m using seems to require it…
git push --dry-run $1 2>&1 | awk '/^ / {print $1}' | xargs git log

(Make sure it’s executable by whomever needs to use it!)

Then, in your git config, add the following section:

[alias]
    out = outgoing

And finally, you should be able to type git out, and see something like:

commit 7d4c9b89a4663a07bed030669bae2d3c73ec78dc
Author: Blake Winton <bwinton@latte.ca>
Date:   Thu Dec 8 12:22:41 2011 -0500

    Blear 2

commit a4e8c6627bc26d7371fb2614a1c47aaf694957bd
Author: Blake Winton <bwinton@latte.ca>
Date:   Thu Dec 8 12:18:04 2011 -0500

    Bleah.

So, hopefully some of the rest of you will find this helpful, too, and if you know of a better way to do this, please let me know in the comments!

Thunderbird’s UI Directions.

On a previous post in a different blog, some commenters were asking us if we were considering doing things that we have planned to do for a while now, and that led me to realize that I haven’t been communicating the future of Thunderbird’s UI nearly well enough. I mainly blame it on my trying to do too many other things, and thus failing to cover all the bases. So, having said all that, here is the list of things, in no particular order, that I would like to see worked on in the next few versions of Thunderbird. But first, I’ld like to say a little bit about why I want them.

I recently heard about someone who said “Thunderbird looks like iTunes”, and while that’s rather complimentary given the amount of time Apple puts into making things look good, it doesn’t really lead me to believe that people can pick our product out of a screenshot. And so one of the overall goals is to make Thunderbird iconic. You can always tell when a screenshot is of Apple mail, based on the layout and the lack of colour, and Firefox is similarly immediately recognizable because of the big circular back button and smaller rectangular forward button. Similarly, I’m hoping to have Thunderbird look different to other apps, while still fitting in on the platform, and maintaining a little consistency with Firefox. Of course, that’s not the only goal, nor even the main goal. My main idea for Thunderbird is to let you focus on the content that’s important to you, and not be distracted by things you don’t care about. Hopefully most of the changes I talk about here will help that, and as a side benefit also help to give us a more unique style.

  • A simple thing that will make the product nicer to use is just to line things up. We’re all over the place, and it should be fairly simple to make this better. There are a couple of bugs that are related to this, and I suspect we could file a few more for various other parts.

  • We want to put the tabs on top, because they let us put the compose and address book into tabs, while still having the appropriate toolbars. (As well, having everything be a tab makes the application more consistent, as described in the next point.)

  • This leads into removing the standalone Compose and Address Book windows. You’ll still be able to open a window for those functions, but it will just be a regular window with a Compose or Address Book tab. (No bugs for this yet. Removals are sensitive things, and we want to get the replacement UI working well before we remove the existing UI.)

  • We really want the Thunderbird button, so that we can hide the menus, and have less Glass on Windows, and make the most common actions easier to find and use.

  • But, to add that button, we first need to see what the most common menu items people use are, therefore we need Test Pilot.

  • We would like to add a HomeTab, to give people a personalized place to land when they start Thunderbird, or open a new window.

  • We would like to merge the Gloda bar and Quick Filter bar, cause duh.

  • Having two different settings locations is too confusing for me, let alone people who don’t care about the details of the product. We want to merge those into a single searchable place for all the settings, a la Mac System Prefs.

  • This next change is more a small, personal thing, rather than part of a grand plan. It was originally suggested by Mike Beltzner, and while I’ve had some time to work on it, I haven’t had enough to push it through to completion. Basically, I’ld like to be able to order my email by date, while grouping it by subject. (This is different than threading, because I don’t care about which replies are to which messages. I just want a single group for the subject, with the messages ordered by date within that group, and the groups ordered by the date of the most recent message.) There’s no bug for this yet, but as mentioned, I started to write an extension, before hitting some annoying bugs that made it hard.

  • Compactify the header. It’s really too big. Well, that’s a bit of a lie. What I really mean here is that we should move the buttons and their toolbar out of the header, to float just above it. This would allow people to easily turn them off (by removing the entire toolbar), and for those of us who like to keep them, it would make them more visually distinct. As an added bonus, in vertical mode, we could merge that toolbar with the other toolbars, to get something like the pictures of what Thunderbird could look like posted by Asa Dotzler.

  • And finally, I think we should remove the Migration Assistant. It was very useful in the 2.0⇒3.0 transition, but it’s been less and less useful as time goes on, and as people have moved more and more onto Thunderbird 3, and 4, and 5… (No bug for this one either, again, because removals are sensitive things.)

See all the bugs in one big list.

Many thank-yous to Alex Faaborg, and areweprettyyet for the code to link the bugs, and the basis of the styling to make them stand out.

A Proposal for Updates with Add-ons.

Add-ons are an important part of many Mozilla products, and many people have noticed that they’ve taken a hit as we’ve switched to the Rapid Release process. To help users have a little more control over how well their Firefox works, I would like to propose the following slight modification to the automatic Update process:

It all starts when Firefox (and Thunderbird) notice an update is available.

We immediately check the user’s add-ons to see if they are compatible, or if there are compatible versions we haven’t downloaded yet.

If all the add-ons are compatible (or will be made so at the next download), we show the NoAddons dialog:

NoAddons dialog

It‘s the same as the current Firefox or Thunderbird update dialog, and as you would expect, the “Ask Later” and “Update Firefox” buttons do the same things that they do now.

On the other hand, if there are in-compatible add-ons, we show the Addons dialog:

Addons dialog

As you can see, we let the user know which add-ons are incompatible, and give the user an extra button at the bottom to do something different.

The new “Update when my add-ons work” button (wording to be clarified later) will check the add-ons periodically, and automatically update Firefox when all the add-ons are compatible. If the add-ons aren’t compatible after a week (period of time to be configurable), the user will be shown this dialog again, with the (hopefully smaller) list of incompatible add-ons.

Showing the user which add-ons are incompatible will let them decide whether the add-ons are important enough to not upgrade, or whether they can live with the (hopefully short) period of reduced functionality.

As always, comments welcome, but keep them polite or they’ll be deleted.

Customization and choice.

A friend of mine recently said:

EVERY behavior aspect of EVERY application should be user-settable if the user is prepared to drill down far enough. No exceptions. Even if the user will be shooting his own foot by messing with it.

I, obviously, disagree with him, and wanted to explain why in a few more characters than Twitter would allow.

While giving the user complete control over every aspect of an application seems like a good idea, there are two slightly-hidden downsides to it.

First, every choice you give the user doubles the amount of testing you have to do. (Okay, it doesn’t exactly double it, but it certainly adds a testing, maintenance, and support burden.) Is it a responsible use of your time to implement these options if less than 1% of your users will ever change them (and risk shooting their own feet), or would it be better for everyone to implement a feature that more people would use?

Second, Emacs notwithstanding, you’ll never get to a great text editor by customizing a mail reader. The whole Unix (and iOS, oddly) philosophy is to write each app to do one thing, and do it well. Not to do a whole bunch of optional things. And if you’re doing only one thing, presenting an option to the user to do it or not doesn’t make a lot of sense.

And finally, because I can’t count, if you offer people too much choice, it imposes a cognitive burden on them which can lead to their making no choices at all, or at least not making them any happier than when they had fewer choices.

To bring this back to the product I’m working on, we are going out of our way to make Thunderbird more usable and part of that is simplifying it by offering fewer, more meaningful choices.

Who should review my change?

One of the big questions I had when I started writing patches was who I should ask to review them. Now that I’ve been in the community for a while, I’ve got a much better sense of who I should be talking to for the type of things I’m likely to write, but there are still times when I want to make a change in a part of the code that I haven’t touched before, and I’m not sure who to ask. In those cases, I usually fall back to a fairly simple (if non-obvious) set of steps to try and figure out who to pick.

  1. Get the list of files I’ve changed.
  2. Get the hg log for those files.
  3. Check through the log for “r=”, and “sr=”.

Of course, that’s a fairly easy set of steps to automate, and so I present my first cut at the automated reviewer chooser!

Of course, there are a lot of things I’ld like to do with this, such as:

  • Improving the documentation.
  • Checking to see how well this script would have done on previous commits.
  • Taking into account the length of the queues for the reviewers.
  • Adding some sort of recent-ness calculations.

But I think that this tool is useful enough in its current state that releasing it and getting feedback on what to actually work on would be a win.

To use it, be in a mercurial source repo, and type getReviewer.py to get a list of suggested reviewers for the current differences, or getReviewer.py temp.diff or getReviewer.py https://bugzilla.mozilla.org/attachment.cgi\?id\=536017 to specify a different set of changes.