LowPro: The essential Prototype companion library to clean up your markup

It’s 2008. There is a short list of things that should never be seen in markup from this point forward:

  • inline event handlers
  • script elements outside of your document’s head

Yes, this includes your Google Analytics tracking scripts. Put those script tags in your document’s head where they belong, and use DOM ready events to fire your tracking.

The key to modern scripting is in your markup. Make it as semantic as you can. Use class names that makes sense, more than one if necessary. Use microformats if you can. Once you do this, you will find id attributes become much less important. I tend to only use them for database objects these days- and even then it can get you into trouble.

There are a lot of third party libraries that expect to be passed an element with an id attribute to function properly. I believe parts of Script.aculo.us are like this. Do not allow these libraries seduce you into adding id attributes where you do not otherwise need them. Behavior-based JavaScript is based around the relationship between elements in the DOM. In most cases, none of the elements need id attributes. From inside behaviors, use DOM traversal methods to find other nodes you need to work with.

...

The core of LowPro revolves around two functions: Event.addBehavior and Behavior.create. Event.addBehavior can map DOM elements to anonymous functions based on CSS selectors:

Event.addBehavior({
   'div.main': function() {
     // 'this' is a reference to a matching DOM node
   },
   'div.secondary,div.tertiary': function() {
     // multiple CSS selectors can be separated by a comma
   }
 });

Event.addBehavior also supports attaching event listeners to DOM elements. Note how the CSS selector has a pseudo-class appended to it:

Event.addBehavior({
   'div.main:click': function(event) {
     // 'this' is a reference to a matching DOM node
     // 'event' it the standard Prototype-extended event object
   }
 });

Now when a user clicks on a page element that matches the selector ‘div.main’, the anonymous function is passed the standard Prototype-extended event object and executed, which is cool. 

No more inline <script> tags FTW. I've been using LowPro all this weekend and I've been quite pleased.

Something to experiment with later... HTML5 editor image copy/paste

HTML5 when implemented is supposed to interact with the system's clipboard. I imagine the following scenario would work:

Until HTML5 copy/paste drag&drop is implemented, you'll have to rely on Flash or a (signed) Java applet to interact with the clipboard.

I would *love* to get this working with our editor. While I love skitch, it could be even easier to paste direct.

Though right now we do support pasting of image URLs (we download them properly to avoid hotlinking) -- and we're working on HTML5 drag and drop support too.

Mobile Safari and the iPad do not support contenteditable. So much for Rich Text Editing and TinyMCE

contenteditable is not supported in Safari on iPhone OS. If you're using contenteditable to enable text input within a styled element (for instance, <p contenteditable> or <div contentediable>), you can replace this styled element with a styled <textarea>. In Safari on iPad, iPhone, Mac OS X, and Windows, you can customize the appearance of <textarea> elements using CSS. If necessary, you can even disable any platform-specific, built-in styling on a <textarea> by specifying -webkit-appearance: none.

Surprising. You can't use rich text editors with your fancy iPad. So, SOL on that one. Seems like a glaring omission that I hope they rectify in iPhone OS 4.

Sadness.

MongoDB wasn't created in a lab

MongoDB wasn’t designed in a lab.  We built MongoDB from our own experiences building large scale, high availability, robust systems.  We didn’t start from scratch, we really tried to figure out what was broken, and tackle that.  So the way I think about MongoDB is that if you take MySql, and change the data model from relational to document based, you get a lot of great features: embedded docs for speed, manageability, agile development with schema-less databases, easier horizontal scalability because joins aren’t as important.  There are lots of things that work great in relational databases: indexes, dynamic queries and updates to name a few, and we haven’t changed much there.  For example, the way you design your indexes in MongoDB should be exactly the way you do it in MySql or Oracle, you just have the option of indexing an embedded field.

The MongoDB creator Eliot and his team are really on to something. Because it just so happens, after years of fighting MySQL, its pretty clear what they're creating is what we want.

How to make multipart split tarballs for backup to S3 to fit under the 5GB limit

If you want to burn the archive to discs, or transfer them to a filesystem with a limited max filesize (say FAT32 with a limit of 4GB per file) then you will have to split the file either during or after archive creation. A simple means is to use the split command. Below are examples of both scenarios. More information than conveyed here can be found in the man pages of split, use man split in a terminal to read. Ensure you keep these archives all together in a directory you label for extraction at a later date. Once the archives are split to a desirable size, they can be burned one at a time to disc.

To Split During Creation

tar -cvpz <put options here> / | split -d -b 3900m - /name/of/backup.tar.gz.
  • The first half until the pipe (|) is identical to our earlier example, except for the omission of the f option. Without this, tar will output the archive to standard output, this is then piped to the split command.
  • -d - This option means that the archive suffix will be numerical instead of alphabetical, each split will be sequential starting with 01 and increasing with each new split file.

  • -b - This option designates the size to split at, in this example I've made it 3900mB to fit into a FAT32 partition.

  • - - The hyphen is a placeholder for the input file (normally an actual file already created) and directs split to use standard input.

  • /name/of/backup.tar.gz. Is the prefix that will be applied to all generated split files. It should direct to the folder you want the archives to end up. In our example, the first split archive will be in the directory /name/of/ and be named backup.tar.gz.01 .

To Split After Creation

split -d -b 3900m /path/to/backup.tar.gz /name/of/backup.tar.gz.
  • Here instead of using standard input, we are simply splitting an existing file designated by /path/to/backup.tar.gz .

To Reconstitute the Archive
Reconstructing the complete archive is easy, first cd into the directory holding the split archives. Then simply use cat to write all the archives into one and send over standard output to tar to extract to the specified directory.

cat *tar.gz* | tar -xvpzf - -C /
  • The use of * as a wild card before and after tar.gz tells cat to start with first matching file and add every other that matches, a process known as catenation, how the command got its name.
  • Afterwards, it simply passes all that through standard output to tar to be extracted into root in this example.

S3 has a 5GB limit. Here's how to tarball your backups up so that you can still throw them over to Amazon (or Cloudfiles, or whomever)

Using resolver for domains

OS X has a very cool feature built into to its resolver: /etc/resolver. It allows you to specify different DNS servers for different domains. After creating the /etc/resolver directory, I can create a /etc/resolver/erdelynet.com file with “nameserver 192.168.25.10″ in it. Now, my Mac will use 192.168.25.10 for resolving erdelynet.com and whatever my ISP assigned me for everythying else.