A droplet is exactly what it sounds like; an icon (representing a script YOU write) you can drag and drop a file, a folder, or groups of either, and make something happen. They are extremely versatile, and as usual, you are only limited by your own imagination. For instance, my kids are amateur musicians that enjoy creating projects in GarageBand. When they have composed something interesting, I can drop the files onto a droplet that imports them into my iTunes library (for subsequent iPod syncing) and then emails them to grandparents. Very simple, clean, and I can modify the droplet any time I want. We are going to start by examining the anatomy of a droplet, so you know all the parts and pieces that you have to work with before we jump into writing one and then using it.
Remember our discussion last time about errors, when I introduced the concept of a native handler? It is the same for droplets; there is a native handler that must be used for it to function correctly. (There is also an optional handler, which we will cover as well, since it is pretty useful.) The required handler is the on open handler, and if it is not in your script somewhere, your droplet won’t work at all.
Before we continue, we should also discuss the unique way this type of script must be saved to be functional. (Although you can save droplets anywhere you wish, I recommend the desktop to begin with, so it will be simple to find and use for testing.) Open up the script below in Script Editor:
on open the_Droppings
display dialog "Hey! you dropped " & (the_Droppings's length) & " item(s) on me!"
end open
Go ahead and compile it to make sure it compiles, then select Save As… from the File menu. In the middle of the Save As dialog window, in the lower half, you will see File Format: and a pull-down menu of different choices. You want to select application once you have decided on a name for this droplet, and save it to your desktop.
That is it. You now have a droplet. Go ahead and play around with it by dragging and dropping files and folders onto it’s icon and see what happens, I’ll wait right here.
Did you notice that regardless of whether you dropped a single file, or a folder full of files onto the icon, the count was always 1? Of course, if you selected multiple files or folders, you got an accurate count of how many you dropped. Good, let’s explore this further. The first line:
on open the_Droppings is the necessary format for the on open handler, complete with a variable name (in this example; the_Droppings) afterwards. You MUST have this pattern in every droplet you devise. The on open handler is expecting a list of files or folder references, and so you need to provide a variable name to hold the alias locations of all the files and folders you drop there. (An alias is simply a reference path to the real location of the file; dropping a file or folder on your droplet doesn’t move it.) You need to remember that a list is expected, even if you only plan on dropping a single file or folder onto your droplet, so that you construct the script inside the handler correctly. In my case, I am only asking for the length of the list of items dropped (the_Droppings’s length) to be reproduced in the display dialog, which is simple.
Let’s say you want a text document that lists the names of the files inside of folders you drop onto the droplet:
on open the_Droppings
tell application "Finder" to set file_Names to the name of every file in item 1 of the_Droppings
set the_Text to ""
repeat with a_Name in file_Names
set the_Text to the_Text & a_Name & return
end repeat
tell application "TextEdit" to make new document with properties {text:the_Text}
end open
In this case, we are only allowing the processing of a single folder, as you can see in the line that tells the Finder to only consider item 1 of the_Droppings. Since we know that the on open handler is expecting a list, we simply tell it to deal with the first item of the list, which would be the only item if you drop a single folder onto the droplet icon. If you try dropping a file onto this droplet, you discover one of the inherent weaknesses of droplets; you get no error information in its native form, even with a try block. (Go ahead and put one in there; you’ll see what I mean.) Fortunately, a droplet only deals with files or folders; nothing else. If your droplet does not function correctly, that often means it is expecting one thing, and receiving the other.
When we tell the Finder to set file_Names to the name of every file in item 1 of the_Droppings, the variable file_Names is also a list, thus requiring us to use the repeat to create the text for the TextEdit document. That repeat is pretty simple; we initially set the variable the_Text to an empty string (“”), and repeat through the list of file_Names, adding each file name and a return to the_Text. Once we get to the TextEdit tell statement, the variable the_Text holds all the filenames, one per line, and we get the nifty document listing all the filenames.
Keep in mind as well that when you drop a folder onto a droplet, and it processes all the files in that folder, they will typically be processed in their Finder sorted order. This is not always going to be the case if you collect a random assortment of files from different locations in your system, or if you drop a few folders of files onto a single droplet. Each folder’s contents may very well be processed in order, but you will not get a final sorting of ALL the files unless you write that code yourself.
It gets tricky when you want to have the freedom of dropping folders, files, or folders containing sub-folders onto a droplet and expecting the droplet to just go on and process all the files in all the droppings in the same fashion. Keep in mind that the on open handler is expecting a list. It cannot know all by itself if that list is a list of folders, files, or a combination, so you need to write that into your code yourself:
on open the_Droppings
set dropped_Files to {}
set dropped_Folders to {}
repeat with a_Drop in the_Droppings
if folder of (info for a_Drop) then
set end of dropped_Folders to a_Drop
else
set end of dropped_Files to a_Drop
end if
end repeat
display dialog "You dropped " & (dropped_Files's length) & " files, and " & (dropped_Folders's length) & " folders just now."
end open
Since a droplet cannot automatiacally discern between folders and files, we loop through the list of dropped items, and simply test to see if it is a folder: if folder of (info for a_Drop) then. If this evaluates to false, it has to be a file, so the script will produce a list of folders (dropped_Folders) and a list of files (dropped_Files) that you can now process however you want.
The info for command is a very convenient term to obtain information about files and folders without invoking the Finder. The list of properties you can access is extensive; look in the StandardAdditions AppleScript library under File Commands.
There is an optional handler that you can use in your droplets that can function as a sort of help file; the on run handler. If you have a few droplets scattered around your system, and you can’t remember what they are there for, double-clicking them will activate the on run handler, which you can use to offer an explanation:
on open the_Droppings
display dialog "Hey! you dropped " & (the_Droppings's length) & " item(s) on me!"
end open
on run
display dialog "This counts the number of dropped items" giving up after 3
end run
It is a good idea to use this handler so that you need not open the script up every time you wonder what it was that you wrote in the first place. In fact, you can take the on run handler one step further and set your droplet up to perform double duty. I only learned of this technique recently (thank you, Bruce Phillips), and have not had much experience with it, but it displays a fundamental strength of AppleScript that I keep needing to remind myself about: Don’t be afraid to try anything.
Here is a sample script of what I am talking about:
on run
choose folder with prompt "Which folder would like average file size calculated?"
open {result}
end run
on open user_Choice
tell application "Finder" to set xx to every file in item 1 of user_Choice
set tot_size to 0
repeat with a_File in xx
set tot_size to tot_size + ((info for (a_File as alias))'s size)
end repeat
display dialog "Total files: " & (xx's length) & return & "Average Size: " & (((tot_size / 1.048576E+6) / (xx's length)) as integer) & " MB"
end open
In this situation, we use the on run section of our droplet script to prompt the user to choose a folder, which is then sent to the on open handler to be processed. We can use the with prompt modifier to act as a brief explanation of what the droplet/application does. This way, not only does the script function as a droplet, it also achieves the ability to work as an application, and double-clicking on the icon will launch it (and explain its purpose) all in one motion. It is currently designed to only act on the first item in the list sent to the handler, but that could be easily modified to deal with a list of folders, so work on that if you are interested. You might also design your handler to prompt the user to choose file instead and then write the script to deal with folders of files as well.
I think that droplets are cool, and I recommend that you consider using them, even for simple tasks. You can drag files and folders out of any Finder window to drop onto your droplet, so don’t feel like you have to keep your droplets in different places to do different things; put them all on your desktop, or in a folder on your desktop, and drop stuff on them from anywhere.