Zero Configuration Web Galleries

Posted on

Tagged as computing, js, applescript and acrylamid

Background

Having migrated to static web generation, a full-featured web gallery system just isn't an option. I don't want or need an RDBMS to store meta-data, and there's certainly no reason to install an entire CMS framework just to pubish some pictures. However, having a four-year-old and a family that doesn't actually live in my back yard makes some kind of web gallery a necessity.

Yes, there are many picture sharing social media venues. All of them:

  • have terms of service that can change with little notice and no consent
  • have some kind of profit motive, mostly undis­closed
  • are conflicted between security and ac­ces­si­bil­i­ty

So we're on our own.

Problem Domain

Our household is firmly planted in the Apple Computer ecosystem. (No, that's not part of the problem!) This means that we have iDevices, and that we use iPhoto and Aperture to deal with the deluge of "kid pictures."

Aperture is fine photo management software, and it is capable of creating "web galleries". That is, it has built-in templates that can be used to export self-contained, nicely-themed, chunks of web space that one can upload to their own server. Un­for­tu­nate­ly, Apple doesn't make it readily apparent how to create your own templates. Also the system to generate the galleries is IMHO more complex than required by the level of flexibiity allowed.

I knew that I wanted a cool Lightbox-style slide show, but I also wanted something that would "just work" if I uploaded a bunch of pictures into a directory. Again, trying to avoid any actual processing on the server.

Solution Landscape

Lightbox Software

I eventually settled on Fancybox for two reasons:

  • It has user-definable callbacks for many events. I was hoping that some of these could be used by other software to pull captions (and other in­for­ma­tion) from the EXIF data in the pictures and display them.
  • It's based on jQuery, and the Javascript EXIF parser that I found also had a jQuery version. Sharing code is good.

I also looked at other im­ple­men­ta­tions:

Meta-data Extraction

Part of the original problem spec­i­fi­ca­tion was to get a "caption" out of "the EXIF data." This goal is mal-formed.

EXIF doesn't really have a place for a "caption" -- there is an exntirely different standard for shoving meta-data into digital pho­tographs called IPTC - which was created by jour­nal­ists.

Of course Aperture does "the right thing" and puts the caption in the IPTC payload, not the EXIF payload. I had found a Javascript im­ple­men­ta­tion of an EXIF parser, not an IPTC parser. Yeah... so auto-captions will have to wait for another day.

Aperture Export

Most Lightbox software requires two images - a full-size version and a thumbail. In my case, I also needed a manifest of the images in order to have Javascript dy­nam­i­cal­ly insert the ap­pro­pri­ate elements into the DOM.

I created three presets in Aperture:

  • export settings for the full-size images
  • export settings for the thumbnail images
  • a directory export setting that put the output in "thumbs" under the target directory

Next, it was straight forward to build Ap­ple­Script that would export the current selection using those presets. It took a little fiddling to get the file names out of the list of version objects, but I evntually made it happen.

Solution

Gallery Export Ap­ple­Script

This is the Ap­ple­Script that exports the current selection into a selected folder in such a way that the Javascript can build the Lightbox:

tell application "Finder"
    set destination to choose folder
end tell
tell application "Aperture"
    set lightbox to first export setting whose name is "Gallery Lightbox"
    set thumbnails to first export setting whose name is "Gallery Thumbnail"
    set dirPolicy to first folder naming policy whose name is "Project Name"
    set thumbDirPolicy to first folder naming policy whose name is "Gallery Thumbnails"
    set oVers to selection as list
    if oVers is {} then
        error "Please select some images to export!"
    else
        -- need to exclude versions with referenced, missing master
        set verList to export oVers using lightbox to destination naming folders with dirPolicy
        set thumbList to export oVers using thumbnails to destination naming folders with thumbDirPolicy


        -- Write one file name per line to MANIFEST
        try
            set projDir to value of other tag "MasterLocation" of the first item in oVers
            set default_delimiters to AppleScript's text item delimiters
            set AppleScript's text item delimiters to ":"
            set manifest to open for access file ((destination as string) & (projDir as string) & ":MANIFEST") with write permission
            repeat with ver in verList
                write text item -1 of (ver as rich text) to manifest as rich text
                write (ASCII character 10) to manifest
            end repeat
            set AppleScript's text item delimiters to default_delimiters
            close access manifest
        on error
            try
                set AppleScript's text item delimiters to default_delimiters
                close access manifest
                return false
            end try
        end try

        display dialog "Export to " & destination & "complete."

    end if
end tell

Dynamic Gallery Javascript

This is the Jacascript that will build a Lightbox, given an export arranged by the preceeding Ap­ple­Script:

   $(document).ready(function() {
       $.get("MANIFEST", function(data) {
           var lines = data.split('\n');    // one pic per line
       var gallery = $('#gallery-container');
       lines = $.grep(lines, function(n){ return(n) }); // remove empty elements

           $.each(lines, function(lineNo, line) {
               $("<a />", {
           "class": "fancybox",
           "data-fancybox-group": "gallery2",
           "href": line,
           "html": $("<img />", {
           "src": "thumbs/" + line
           })
       }).appendTo(gallery);
           }); // each

       }); // get MANIFEST


       /*
    *  Simple image gallery. Uses default settings.
    */

       $('.fancybox').fancybox({
           afterLoad: function() {
           }, // afterLoad
           beforeShow: function() {
           } // beforeShow
       }); // fancybox
   }); // ready

Apache Con­fig­u­ra­tion

In my web space, each gallery is a sub-folder of /pics. In order to avoid special set-up for each new gallery, we to do the following:

  • let mod_index create the list of galleries, prepending a header and appending a footer generated for the web site theme -- this is the only server-side "pro­cess­ing"
  • for any sub­di­re­to­ry of /pics, use gallery.html as the index file (for the index.html document or just the gallery location URL)

This .htaccess fragment ac­com­plish­es that:

Options +FollowSymlinks
IndexOptions NameWidth=*
IndexIgnore FOOTER* gallery.html

HeaderName HEADER.HTML
ReadmeName FOOTER.HTML

RewriteEngine on
RewriteCond %{HTTPS} off
RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI}

RewriteBase /pics
RewriteRule ^.+/$ /pics/gallery.html [L]
RewriteRule ^.+/index.html$ /pics/gallery.html [L]

Summary

It's not trivial, but all of the components are pretty simple. At least now I can spend my gallery management time curating pictures.

FairTax OS X TSA acrylamid applescript computing food frugal government hazel js music woodworking