      // Default ordering for snapshots.
      var ordering = "most_recent";
      // Default page to be fetched. Altered by bin_to_snapshot and page_to_snapshot
      var page = 1;

      // Maximum amount of snaphots to be fetched per request
      var per_page = 10;

      // Root URL for creating HREFs etc...
      var url;
      // url_str should be defined on the page
      if (url_str) {
        url = url_str;
      } else {
        url = "http://www.gigapan.org/alpha/";
      }
      // Media URL for JPEGs, stylesheets, etc...
      var media_url = "http://www.gigapan.org/alpha/";

      // Returns a formatted URL for linking to conversations
      function conversation_url(url, id) {
        if (url.lastIndexOf("/") != (url.length - 1)) {
          url += "/";
        } 
        return url + "conversations/" + id + "/";
      }

      // Returns a formatted URL for IMG elements
      function snapshot_url(media_url, id, width, height) {
        if (media_url.lastIndexOf("/") != (media_url.length - 1)) {
          media_url += "/";
        } 
        return media_url + "snapshots/" + id + "-" + width + "x" + height +".jpg";
      }

      // Returns a formatted URL for linking to user profiles
      function profile_url(url, owner) {
        if (url.lastIndexOf("/") != (url.length - 1)) {
          url += "/";
        } 
        return url + "profiles/" + owner.id + "/";
      }

      // Returns a formatted string identifying users 
      function format_username(owner) {
        if (owner.first_name && owner.last_name) {
          str =  owner.first_name + " " + owner.last_name + " ";
        } else {
          str = "";
        }
        return str + "(" + owner.username + ")";
      }

      // Returns a formatted date string (Month Day, Year)
      function format_date(created) {
        return DateUtils.createSimpleDateString(DateUtils.parseDate(created));
      }

      // Return the number of comments in the comment set or 0
      function format_comments(comment_set) {
        if (comment_set) {
          return comment_set.count;
        } else {
          return 0;
        }
      }

      // Append the necessary HTML to #snapshot_bar
      function toHTML(snapshot) {
         if (snapshot.id == snapshot_id) {
          div_class = "SnapshotAsListItem Active";
        } else {
          div_class = "SnapshotAsListItem";
        }
        $("#snapshot_bar").append(
        '<div class="' + div_class + '">' +
        '  <div class="SnapshotThumbnail">' +
        '    <a href="'+ conversation_url(url, snapshot.id) + '"><img src="' + snapshot_url(media_url, snapshot.id, 90, 70) +'" width="89" height="67" border="0" alt=""/></a>' +
        '  </div>' +
        '  <div class="SnapshotProperties">' +
        '    <p style="font-weight:bold;"><a href="' + conversation_url(url, snapshot.id) + '">' + snapshot.name + '</a></p>' +
        '    <p>Snapped By: <a href="' + profile_url(url, snapshot.owner) + '">' +  format_username(snapshot.owner) + '</a></p>' +
        '    <p>Created: ' + format_date(snapshot.created) + '</p>' +
        '    <p>Comments: ' + format_comments(snapshot.comment_set) + '</p>' +
        '  </div>' +
        '  <div class="SnapshotAsListItemFooter"></div>' +
        '</div>'
        );
      }

      // FIXME: THIS SHOULD PROBABLY BE ITS OWN CLASS
      var pagination_range = 5;
      var pagination_offset = Math.floor(pagination_range/2);

      // Appends pagination related elements to #pagination_bar_top and #pagination_bar_bottom
      function pagination_bar(page, per_page, count, available) {
        if (page == 1) {
          prev = '< prev';
        } else {
          prev = '<a href="javascript:void(0)" onclick="get_snapshots(gigapan_id, ' + (page - 1) + ', per_page,ordering)">< prev</a>';
        }
      
        if (count < per_page || count*page == available) {
          next = 'next >';
        } else {
          next = '<a href="javascript:void(0)" onclick="get_snapshots(gigapan_id, ' + (page + 1) + ', per_page,ordering)">next ></a>';
        }

        max_pages = Math.ceil(available/per_page);
        current_page = page;
        if (max_pages > pagination_range) {
          if (current_page - pagination_offset > 0) {
            start_page = current_page - pagination_offset;
            end_page = current_page + pagination_offset;
          } else {
            start_page = 1;
            end_page = pagination_range;
          }
          if (end_page > max_pages)  {
            end_page = max_pages;
            start_page = max_pages - pagination_range;
          }

        } else {
          start_page = 1;
          end_page = max_pages;
        }
        range = "";
        for (i = start_page; i <= end_page; i++) {
          if (i == current_page) {
            range += i;
          } else { 
            range += '<a href="javascript:void(0)" onclick="get_snapshots(gigapan_id, ' + i + ', per_page,ordering)">' + i + '</a>';
          }
          if (i != end_page) {
            range += " "
          }
        }        

        var start = (page  - 1)*per_page + 1;
        var end;
        if (count == per_page) {
          end = count*page;
        } else {
          end = available;
        }
        $("#pagination_bar_top").html("");
        $("#pagination_bar_top").append(
          '<table border="0" cellpadding="0" cellspacing="0" width="100%">' +
          '  <tr>'                                                          +
          '    <td>'                                                        +
          '      <div CLASS="status_bar" style="font-size:12px">'          +
          '        <div CLASS="left"> ' + start  + ' to ' + end + ' of ' + available + '</div>'      +
          '        <div class="center"></div>'                              +
          '        <div CLASS="center"></div>'                              +
          '        <div CLASS="right">' + prev + ' ' + range + ' ' + next + '</div>'               +
          '      </div>'                                                    +
          '    </td>'                                                       +
          '  </tr>'                                                         +
          '</table>' 
        );

        $("#pagination_bar_bottom").html("");
        $("#pagination_bar_bottom").append(
          '<table border="0" cellpadding="0" cellspacing="0" width="100%">' +
          '  <tr>'                                                          +
          '    <td>'                                                        +
          '      <div CLASS="status_bar" style="font-size:12px">'          +
          '        <div CLASS="left"> ' + start  + ' to ' + end + ' of ' + available + '</div>'      +
          '        <div class="center"></div>'                              +
          '        <div CLASS="center"></div>'                              +
          '        <div CLASS="right">' + prev + ' ' + range + ' ' + next + '</div>'               +
          '      </div>'                                                    +
          '    </td>'                                                       +
          '  </tr>'                                                         +
          '</table>' 
        );
      }

      // Clear the contents of #snapshot_bar and then add all snapshots formatted as HTML
      function add_snapshots(data) {
        $("#snapshot_bar").html("");
        $.each(data.items, function(i, item) { 
          snapshot = item[1];
          toHTML(snapshot);
        });     
      }


      // Set the variables in the API URL
      function set_api_url(gigapan_id, page, per_page, ordering) {
        var str = "/gigapans/" + gigapan_id + '/snapshots/page/' + page + '/per_page/' + per_page + '/' + ordering + '.json';
        return str;
      }
      

      // API fetch for JSON snapshots
      function get_snapshots(gigapan_id, page, per_page, ordering) {
        str = set_api_url(gigapan_id, page, per_page, ordering);
        $.getJSON(str + "?callback=?", 
          function(data){
            if (data.count != 0) {
              if (data.available > 10) {
                pagination_bar(page, per_page, data.count, data.available);
              }
              add_snapshots(data);
            }
          }
        );
      }

      // Iterate through the paginated snapshot collections until the specified snapshot_id is found
      function page_to_snapshot(gigapan_id, page, per_page, ordering) {
        str = set_api_url(gigapan_id, page, per_page, ordering);
        $.getJSON(str + "?callback=?", 
          function(data){
            if (data.count != 0) {
              if (data.items[data.count - 1][0] > snapshot_id) {
                page++;
                page_to_snapshot(gigapan_id, page, per_page, ordering);
              } else {
                if (data.available > 10) {
                  pagination_bar(page, per_page, data.count, data.available);
                }
                add_snapshots(data);
              }
            }
          }
        );
      }

      var left = 0;
      var right = 0;

      // Binary search through the paginated snapshot collections until the snapshot is found
      // Assumes the ordering is most_recent and snapshot_ids are still being generated as unique auto incremented keys
      function bin_to_snapshot(gigapan_id, page, per_page, ordering) {
        str = set_api_url(gigapan_id, page, per_page, ordering);
        $.getJSON(str + "?callback=?", 
          function(data){
            // initial case
            if (left == 0 && right == 0) {
              left = 0;
              right = Math.ceil(data.available/per_page) + 1;
              page = Math.floor((right + left) / 2);
              bin_to_snapshot(gigapan_id, page, per_page, ordering);
            } else {
              // case that page = 1 and snapshot is still greater than id
              if (page == 1 && snapshot_id > data.items[0][0]) {
                get_snapshots(gigapan_id, page, per_page, ordering);
              } else if (page ==  Math.ceil(data.available/per_page) && snapshot_id <  data.items[data.count - 1][0]) {
                //alert('bottom');
                get_snapshots(gigapan_id, page, per_page, ordering);
              } else {
                // case that page = last possible page and snapshot is less than least possible
                if (snapshot_id > data.items[0][0]) {
                  right = page;
                  page = Math.floor((right + left) / 2);
                  //alert('shifting right! left: ' + left + ', right: '+ right + ', page: ' + page);
                  bin_to_snapshot(gigapan_id, page, per_page, ordering);
                } else if (snapshot_id < data.items[data.count - 1][0]) {
                  left = page;
                  page = Math.floor((right + left) /2);
                  //alert('shifting left! left: ' + left + ', right: '+ right + ', page: ' + page);
                  bin_to_snapshot(gigapan_id, page, per_page, ordering);
                }
                else {
                  // display this page
                  get_snapshots(gigapan_id, page, per_page, ordering)
                }
              }
            }
          }
        );
      }
