Fotorama Slide Show and phpSmug

Fotorama Web Site Home Page

Fotorama

As a part of my web site moving and redesign I wanted to include a slideshow at the top of the home page.

After researching and thinking about writing one of my own I found Fotorama which is a jQuery based slideshow framework that allows for many different types of slideshows with a ton of options. Take a look at the website and the examples, they are amazing.

So I broke the process down into a handful of steps and iterated up to the dynamic slideshow that it is now.

The first step was getting a version running on a test page with static content hard-coded into the page. There was a bit of tweaking here and there along with coming up with the idea to have a design that resembles a new window "Window" with Hide and Fullscreen buttons.

The next step was figuring out how to dynamically get the picture URLs and Captions directly from SmugMug so that anytime I update SmugMug the slidesow on my website would also be updated. For that I chose to use phpSmug which is a wrapper class for the SmugMug API written and maintained by Colin Seymour.

I ran into 2 issues with implementing phpSmug, the biggest of which was that it would randomly error out with a "CURL Error 7" which was causing my website to load very slowly and breaking the slideshow. I have addressed this issue by using the caching built into phpSmug combined with writing the parsed data necessary for the slideshow into a MySQL table. Anytime the SmugMug API is not available and the phpSmug cache has expired the data for the slideshow will be pulled from the database.

Here is the code:


<?php
$user="username";
$password="password";
$database="database_name";
$tablename="table_name";
mysql_connect(localhost,$user,$password);
@mysql_select_db($databaseor die"Unable to select database");
/* Last updated with phpSmug 3.0 */
require_once"/path/to/phpSmug.php" );
try {
  $code = "SmugMug API";
  // My API Key and App Name from SmugMug Admin Panel
  $f = new phpSmug"APIKey=api_key""AppName=app_name_and_version" );
  // Enable disk based caching with expires in 1 hour
  $f->enableCache("type=fs""cache_dir=/path/to/phpsmugcache""cache_expire=3600" );
  // Set timeout
  $f->req->setConfig(array'timeout' => 2));
  // Login Anonymously
  $f->login();
  // Get images from Portfolio
  $images = $f->images_get"AlbumID=album_id""AlbumKey=album_key""Heavy=1" );
  $images = ( $f->APIVer == "1.2.2" ) ? $images['Images'] : $images;
  $i = 0;
  foreach ( $images as $image ) {
    if ($i != 0) {
      $query .=  ",\n";
      $output .=  ",\n";
    }
    $i++;
    // Create SQL String
    $query .= "('','".$image['X2LargeURL']."','".$image['TinyURL']."','".htmlentities($image['Caption'],ENT_QUOTES)."')";
    $output .= "{img: \"".$image['X2LargeURL']."\", thumb: \"".$image['TinyURL']."\", caption: \"".htmlentities($image['Caption'])."\"}";
  }
  // Empty Out Table
  mysql_query('TRUNCATE TABLE '.$tablenameor die(mysql_error());
  // Populate Table
  mysql_query("INSERT INTO cache (`id`, `x2largeurl`, `tinyurl`, `caption`) VALUES ".$query);
} catch ( Exception $e ) {
  $code = "{$e->getMessage()} (Error Code: {$e->getCode()})";
  //Read from Database
  $query="SELECT * FROM ".$tablename;
  $result=mysql_query($query);
  $num=mysql_numrows($result);
  $i=0;
  while ($i < $num) {
    $X2LargeURL=mysql_result($result,$i,"x2largeurl");
    $TinyURL=mysql_result($result,$i,"tinyurl");
    $Caption=mysql_result($result,$i,"caption");
    if ($i != 0) {
      $output .=  ",\n";
    }
    $i++;
    // Create SQL String
    $output .= "{img: \"".$X2LargeURL."\", thumb: \"".$TinyURL."\", caption: \"".$Caption."\"}";
  }
}
mysql_close();
?>
jQuery(document).ready(function(){
  try { console.log('code: <?php echo $code ?>'); } catch(err) { }
  // Load Fotorama.js script
  jQuery.getScript("/scripts/fotorama.js"function(){
    var portfolioBuildFlag = false;
    jQuery('#main').prepend('<article class="fotoramaWrapper"><div class="portfolioHeader gradient">Dave Nelson's Portfolio <div><span id="portfolioHide">[ Hide ]</span> <span id="portfolioFullScreen">[ Fullscreen ]</span></div></div><div id="myPortfolio"></div></article>');
    jQuery('#portfolioHide').on('click',portfolioToggle);
    jQuery('#portfolioFullScreen').on('click',function() {
      if(jQuery("#myPortfolio").is(":hidden") || portfolioBuildFlag === false) {
        portfolioShow();
      }
      jQuery('#myPortfolio').trigger('fullscreenopen');
    });
    function portfolioBuild() {
      jQuery('#myPortfolio').fotorama({
        data: [
        <?php
          echo $output."\n";
        ?>
        ],
        width'100%',
        height'auto',
        aspectRatio1.5,
        minHeight500,
        fitToWindowHeightfalse,
        margin0,
        shadowsfalse,
        cropToFitfalse,
        caption'overlay',
        autoplay3000,
        thumbBorderColor'#FCB03E',
        fullscreenIcontrue
      });
      portfolioBuildFlag = true;
    }
    function portfolioCookie(state) {
      if (state === "hidden") {
        document.cookie = "portfolioHide=true";
      } else {
        document.cookie = "portfolioHide=false";
      }
    }
    function portfolioToggle() {
      if(jQuery("#myPortfolio").is(":hidden") || portfolioBuildFlag === false) {
        portfolioShow();
      } else {
        portfolioHide();
      }
    }
    function portfolioShow() {
      if (portfolioBuildFlag === false) {
        portfolioBuild();
      }
      jQuery('#myPortfolio').slideDown('fast');
      jQuery('#portfolioHide').text('[ Hide ]');
      jQuery('#myPortfolio').trigger('play')
      portfolioCookie('shown');
    }
    function portfolioHide() {
      jQuery('#myPortfolio').slideUp('fast');
      jQuery('#portfolioHide').text('[ Show ]');
      jQuery('#myPortfolio').trigger('pause')
      portfolioCookie('hidden');
    }
    function portfolioInit() {
      var portfolioHide = document.cookie.replace(/(?:(?:^|.*;\s*)portfolioHide\s*\=\s*((?:[^;](?!;))*[^;]?).*)|.*/"$1");
      if (portfolioHide != "true") {
        portfolioBuild();
      } else {
        jQuery('#portfolioHide').text('[ Show ]');
      }
    }
    portfolioInit();
  }); // Load Fotorama.js script

}); // document ready

Pro jQuery by Adam Freeman

I read this book on Safari Books Online using Firefox.

I am doing more and more with jQuery and went looking for a book that could show me the ins-and-outs of it and "Pro jQuery" is definitely that book.

I do not agree that this is a “Pro” book as it does not cover professional techniques for programming in JavaScript using the current best practices that you would find in a production environment, but this book is a great reference for jQuery and I could find none that were better.

This book has taken my jQuery skills from advanced newbie to a solid understanding of what I would use jQuery for and what I would not. I expect to use it as a reference for a long time to come.

From the publisher:

Query is one of the most popular and powerful JavaScript libraries available today. It’s widely used to create rich user experiences and to simplify website and application development. It is the tool of choice for web developers everywhere and sets the standard for simplicity, flexibility and extensibility.

In Pro jQuery, seasoned author Adam Freeman explains how to get the most from jQuery by focusing on the features you need for your project. He starts with the nuts and bolts and shows you everything through to advanced features, going in depth to give you the knowledge you need. Getting the most from jQuery is essential to truly mastering web development.

What you’ll learn

  • Understand the capabilities of jQuery and why it is special
  • Use the core of jQuery to enrich HTML, including tables, forms and data displays
  • Use jQuery UI to create rich and fluid user experiences
  • Use rich interactions such as drag and drop, sortable data and touch sensitivity
  • Use jQuery Mobile to create touch-enabled interfaces for mobile devices and tablets
  • Extend jQuery by creating custom plugins and widgets

Each topic is covered clearly and concisely, and is packed with the details you’ll need to learn to be truly effective with jQuery. The most important features are given a no-nonsense, in-depth treatment, and chapters contain examples that demonstrate both the power and the subtlety of jQuery.

I rate this book an 8 out of 10 and recommend it to anyone interested in learning more about jQuery.

Responsive Design in Practice

What the heck does "Repsonsive" mean when it comes to a web site?

For my own practical purposes it means that I have a single web site with one set of HTML, CSS, and JavaScript being served to all web browsers, but the appearance of the website changes based upon the width of the web browser’s window to give a great viewing experience to everyone.

Haha, that is a mouthful.

So here it is in action:

davenelson.com Desktop Web Browser Screen Shot

Desktop Web Browser


davenelson.com iPad Screen Shot

iPad


iPhone

davenelson.com iPhone Screen Shot

The great thing is I did not need to build three different websites, no "mobile" version, just "The Website." Another great thing is that I was able to start with a WordPress theme that someone else spent a lot of time an effort in building. I just tweaked it to fit my needs.

Sunspot WordPress Theme Screen Shot

Sunspot WordPress Theme Screen Shot

The theme is called Sunspot by Automattic and I really like the way my content looks when using it.

From the author:

A sharp theme with subtle grid lines and sun-splashed accents, Sunspot is a great all-purpose blogging canvas, especially for those who prefer a dark color scheme. Sunspot offers two arrangements for posts on the front page. Additional features include a custom header and a custom background, two optional widget areas, and a responsive layout that adapts gracefully to smaller screen sizes.

Responsive design is not a fit for all web sites, content and interactions that work great in a desktop web browser are not always appropriate for the really small screens of smartphones and conversely content made for smartphones does not always scale well for big screens. But for a blog or any site that is primarily text-based I think responsive design is a great way to reach a broader audience.