Assorted, Scattered JavaScript Notes
Boolean(value) method returns false for falsey values, true for truthy values
falsy: false, null, undefined, "", 0, NaN
truthy: everything else: "0", "false"
+ as a leading operator converts a string to a number: +"42" = 42. Same as Number("42") = 42), parseInt("42", 10) = 42
+"3" + (+"4") = 7
=== !== do not do type coercion, slightly faster
if (a) {
return a.member;
} else {
return a;
}
can be written as
return a && a.member;
if the first operand is truthy, return the second operand, else, return the first
but for || if the first operand is truthy, return the first operand, else, return the second:
var last = input || somethingElse;
so if input is truthy, then last is input, otherwise set last to somethingElse
you can label loops and break them by label:
myloop: for (whatever)
{
break myloop;
}
//other loop
for (var name in object) {
if (object.hasOwnProperty(name)) //avoids looking at objects we might have inherited from
{
name //is the current member
object[name] //is the current member value
}
}
//multiple conditions in switch statements
switch(something) {
case ";";
case ",";
case ".";
isPunctuation();
break;
default:
somethingElse();
}
//exceptions and object literals
throw new Error(myReason);
throw { //create an "object literal" creates an exception object on the fly
name: myexceptionName,
message: reason
};
//object literals
an object literal is wrapped in { }
a name can be a names or a value
values are any type
: seperates names and values
, seperates pairs
object literals can be used anywhere a value can appear
var myObject = {name: "Jack", 'goto': 'Jail', grade: 'A', level: 3};
var myName = myObject.name; //extracts "Jack"
var destination = myObject['goto']; //extracts "Jail"
var destination = myObject["name"]; //extracts "Jack"
var destination = myObject[goto]; //returns an error because goto is a reserved word, hence the other notation
//maker function
function maker (name, grade)
{
var it = {}; //makes a new empty object, good shorthand
it.name = name;
it.grade = grade;
return it;
}
var myObject = maker("Jack", "A");
//an object with an object as a member, shorthanded
var myObject = {
name: "jack",
grade: "a",
clothes: {
pants: 'blue',
shirt: 'red'
}
};
//if you have more than a couple parameters in a function, why not make them an object?
function myfunc(pa, pb, pc, pd, pe, pf)
myfunc(pa, pb, pc, pd, pe, pf)
vs.
function myfunc(specs)
myfunc({ pa: '1', pc: '3', pb:'2', ... })
** note: variables that are not var'ed become implicitly global
//specify object's prototype on creation? linkage -- doesn't really exist
var newObject = object(otherObject);
//gives it a secret pointer to otherObject, but the secret pointer is used for retrieving only NOT storing
//object (lowercase) is a method that Yahoo made up
//different than
var newObject = Object() which equals: var newObject = object(Object.prototype)
delete myObject[memberName]; //deletes (sets to undefined) a member of an object
myArray[myArray.length] = 3 //appends to end of array (same as pop)
var myArray[] //creates a new array?
Using Mail.app with multiple users — using AppleScript!
OK, this is pretty brilliant -- and SO simple.
Here's the setup: my wife and I share a Mac at home. For memory reasons, among others, I don't want to use Fast User Switching, and because of my automated tasks, I don't want the primary account to ever be logged out. So all many of our programs need to be set-up for two different users. Firefox has user profiles, that once configured, works perfect. Mail.app has no such thing. What I decided to then, was write an AppleScript that would switch Mail.app between users for us. This example is for two users, but it could be edited for more. Here's how to use it:
- Setup Mail accounts for each user
- Modify the script to prompt for each user you have, and reference their account name
- Replace your Mail.app dock icon with a link to your AppleScript (you can even give it the Mail.app icon)
- Whenever you launch Mail, you'll be asked which user you want to use
- Even better than that, you can switch users just by clicking the Mail icon in your dock again. You don't even have to close down Mail!
The result looks like this whenever you invoke the script, and launches/reconfigures Mail within two seconds. Set the delay to longer if Mail.app takes longer to start on your Mac.

The code is dead simple, and took me only moments to put together. Note that the delays and the order in which things are done is important so that it doesn't hang waiting for Mail to start if its not already open.
-- Mail Account Chooser, by Jonathan Wise
-- Add user profiles to Mail.app
display dialog "Choose the Mail account to use" buttons {"Jonathan", "Elizabeth"} default button 1 with icon note
if the button returned of the result is "Jonathan" then
tell application "Mail"
activate
delay 2
set enabled of account "Elizabeth Home" to false
set enabled of account "Jonathan Home" to true
end tell
else
tell application "Mail"
activate
delay 2
set enabled of account "Jonathan Home" to false
set enabled of account "Elizabeth Home" to true
end tell
end if
Detecting the presence of a given font in .NET
Maybe this seems obvious to other people, but I couldn't find anything in Google on it. Maybe I didn't know the right keywords to search for.
At any rate, lets say you have an application that's optimized for a specific font -- but you can't guarantee that font is installed. You might want to, as a contingency, fall-back to a different font -- maybe one that isn't quite as attractive, but that you know for sure will be present. This other font might have slightly different sizing, so in the case where you fall back, you might want to tweak your UI widgets, or alignment margins and widths, to look better if the fall-back is used. Here's my solution (C#)...
Font fnt = new Font("GoodLookinFont", 10);
if (fnt.FontFamily.Name != "GoodLookinFont")
{
//adjust display for fall-back font
}
What happens is simple: .Net attempts to create a Font object using your preferred font. If it can't find that font on the local system, it will instead create the Font object using "Microsoft Sans Serif." If the Font object's FontFamily Name is not what you expect, you know you'll have to adjust your display.
Automagic
Well my previous post on Symlinks was only partially right. It turns out iTunes doesn’t work very well when it has to share its library. If either computer decides it needs to write anything to the library database, it locks the other out. I had other problems with symlinking iCal’s database — it seems to keep a cache somewhere that I can’t find. So I had to resort to some AppleScripting — maybe the most elite AppleScript I’ve ever written. Here’s everything, some scripted, some not, that our computers do automatically for us…
Media Synchronization
My uber-script runs at 1:00am on the iMac. It starts by cleaning out the downloads folder, deleting any downloaded TV shows over 21 days old, then moves any downloaded music into the appropriate folder and adds it to the local iTunes library. Then it gets really clever, and logs into the remote Home Theater Mac over SSH and begins sending it instructions. It shuts down the remote iTunes, deletes its Library (which is a data island, because we do all our media maintenance on the iMac) and copies over the iMac’s iTunes Library. Note that it copies the Library only — the music remains on a network share that both computers have access to.
Then, once both iTunes are in sync, it starts up the remote iTunes which triggers a sync with my iPhone, getting me a playlist of my most recent music, plus my favorites (I only have a 4GB so I have to manage well) and does something similar locally to sync Nic’s iPod.
Both computers use the network shared Videos folder to populate FrontRow with our movies and TV content.
Calendar Synchronization
I failed to get WebDAV up and running on my new host, and Symlinks didn’t work out. But a wonderful and free service called iCalX came to the rescue. Microsoft finally added WebDAV publishing to Outlook 2007, so I publish my work calendar from there, my personal calendar syncs from my iPhone with the Home Theater Mac and from there to iCalX, and Nic publishes her calendar from the iMac. Any WebDAV client can subscribe to them and iCalX provides a nice little PHP iCalendar view online.
Address Book Synchronization
The OS X Address Book doesn’t complain too much about sharing its library between two computers, and provides little other utility for syncing or sharing (unless you want to pay $99 a year for .Mac — an otherwise useless service). I explored lots of options, but the only unattended one is Exchange syncing (or Kerio), and I don’t want to run a mail server any more. So I finally just decided to let Address Book share. The only caveat is that to make sure Address Book’s on multiple machines match up you have to quit Address Book to dump its in-memory cache and force it to re-read the database. It was easy enough to add some quit, open and hide commands to my uber-script, and that seems to solve the problem. Putting those commands in before each iTunes syncs with its connected portable device makes sure that both the iPhone and iPod have the latest contacts.
Nic’s cell phone is still a non-Apple device, but it syncs nicely over Bluetooth. A little app called Proximity detects when she comes into range of the Home Theater Mac, and fires a tiny AppleScript that does an automatic sync for her. A little blue light on her phone is the only indicator that its even happening.
Document Backup
This is actually another potentially useful service of .Mac, but I’m too cheap to be sold that easily. A really nice online service called Mozy provides free back-ups up to 2GB, and unlimited back-up for $5 a month (sign-up with that link and get me more free space!) We just eeked in under the 2GB mark backing up all our documents. This happens automatically every Sunday night at 1:00am, in place of the usual media sync.
I’ll be taking a semi-annual physical back-up of our document, music and pictures — pictures are copied between both Macs anyway. I have yet to figure out a way to back up 280GB of videos, save for having a second hard drive stored elsewhere, but I think, in case of a fire, we can live with only losing our movie collection.
Cleaning up
After either scheduled task (media sync or back-up, depending on the night of the week) the iMac goes to sleep until 9:00am, or until called for, while the Home Theater Mac studiously downloads things it thinks we might want to watch.
My script is likely pretty unique to our set-up, but I had to search long and hard to find the various parts that make it work — sending script instructions to a remote Mac over SSH was particularly tricky — so I’m posting it here for anyone who’s interested in picking it apart.
One other thing to be aware of, much of the script works against a shared drive, so it needs to be mounted for this to work. I use a little app called Automount Maker to get my media share to mount on boot, but its possible for the volume to get dismounted during the day (our microwave interferes with our wireless, for example, because there are so many wireless networks around, and that can kill the connection). I’d love to hear any ideas on how to make sure a volume stays mounted!